【问题标题】:Automatically scroll down chat div自动向下滚动聊天 div
【发布时间】:2014-10-19 18:37:56
【问题描述】:

我有这段代码,用来加载聊天

function getMessages(letter) {
  var div = $('#messages');
  $.get('msg_show.php', function (data) {
    div.html(data);
  });
}

setInterval(getMessages, 100);

我必须添加什么,以便在页面加载时自动向下滚动 #messages div,并在每个新的聊天帖子中再次滚动?

这不起作用:

function getMessages(letter) {
  var div = $('#messages');
  $.get('msg_show.php', function (data) {
    div.html(data);
    $('#messages').scrollTop($('#messages')[0].scrollHeight);
  });
}

setInterval(getMessages, 100);

【问题讨论】:

  • 如果元素的 ID 是 messages,则应该是 document.getElementById('messages')(注意缺少的 #)。
  • 对不起,我实际上没有#。

标签: javascript jquery scroll chat


【解决方案1】:

让我们先回顾一些关于滚动的有用概念:

什么时候应该滚动?

  • 用户首次加载消息。
  • 新消息已到达,您位于滚动底部(当用户向上滚动以阅读以前的消息时,您不希望强制滚动)。

以编程方式:

if (firstTime) {
  container.scrollTop = container.scrollHeight;
  firstTime = false;
} else if (container.scrollTop + container.clientHeight === container.scrollHeight) {
  container.scrollTop = container.scrollHeight;
}

完整的聊天模拟器(使用 JavaScript):

https://jsfiddle.net/apvtL9xa/

const messages = document.getElementById('messages');

function appendMessage() {
	const message = document.getElementsByClassName('message')[0];
  const newMessage = message.cloneNode(true);
  messages.appendChild(newMessage);
}

function getMessages() {
	// Prior to getting your messages.
  shouldScroll = messages.scrollTop + messages.clientHeight === messages.scrollHeight;
  /*
   * Get your messages, we'll just simulate it by appending a new one syncronously.
   */
  appendMessage();
  // After getting your messages.
  if (!shouldScroll) {
    scrollToBottom();
  }
}

function scrollToBottom() {
  messages.scrollTop = messages.scrollHeight;
}

scrollToBottom();

setInterval(getMessages, 100);
#messages {
  height: 200px;
  overflow-y: auto;
}
<div id="messages">
  <div class="message">
    Hello world
  </div>
</div>

【讨论】:

  • 2019 年 1 月 16 日,现在一直自动向下滚动
  • 如果您的容器具有非整数高度,您可能需要使用container.scrollTop + container.clientHeight &gt;= container.scrollHeight 作为测试。
  • 我现在无法向上滚动
【解决方案2】:

不知道 HTML 代码很难说,但我假设您的 div 没有设置高度和/或不允许溢出(例如通过 CSS height: 200px; overflow: auto)。

我在 jsfiddle 上做了一个工作示例:http://jsfiddle.net/hu4zqq4x/

我在一个 div 中创建了一些虚拟的 HTML 标记,它 a) 溢出并且 b) 具有设定的高度。 滚动是通过调用函数完成的

function getMessages(letter) {
    var div = $("#messages");
    div.scrollTop(div.prop('scrollHeight'));
}

,在这种情况下,在“documentReady”上一次。

prop('scrollHeight') 将访问匹配元素集中第一个元素的属性值。

【讨论】:

    【解决方案3】:

    在 JQuery 中追加后,只需添加这一行

    <script>
        $("#messages").animate({ scrollTop: 20000000 }, "slow");
    </script>
    

    【讨论】:

      【解决方案4】:

      你需要做的就是把它分成两个div。一个溢出设置为滚动,一个内部用于保存文本,这样你就可以得到它的外部大小。

      <div id="chatdiv">
          <div id="textdiv"/>
      </div>
      
      textdiv.html("");
      $.each(chatMessages, function (i, e) {
          textdiv.append("<span>" + e + "</span><br/>");
      });
      chatdiv.scrollTop(textdiv.outerHeight());
      

      你可以在这里查看一个 jsfiddle:http://jsfiddle.net/xj5c3jcn/1/

      显然,您不想每次都重建整个文本 div,因此请谨慎对待 - 只是一个示例。

      【讨论】:

        【解决方案5】:

        如果你只是滚动高度,当用户想要查看他之前的消息时会出现问题。所以你需要做一些事情,当新消息到来时只有代码。使用 jquery 最新版本。 1.在这里我检查了消息加载前的高度。 2.再次检查新高度。 3.如果高度不同,只有那一次它会滚动,否则它不会滚动。 4.不在if条件下你可以放任何铃声或你需要的任何其他功能。将在新消息到来时播放。谢谢

        var oldscrollHeight = $("#messages").prop("scrollHeight");
        $.get('msg_show.php', function(data) {
            div.html(data);
            var newscrollHeight = $("#messages").prop("scrollHeight"); //Scroll height after the request
            if (newscrollHeight > oldscrollHeight) {
                $("#messages").animate({
                    scrollTop: newscrollHeight
                }, 'normal'); //Autoscroll to bottom of div
            }
        

        【讨论】:

        • 终于找到了一个对我有用的解决方案,谢谢:)
        【解决方案6】:

        简单的解决方案:

        1 - 放置在消息的底部(内部)

        <a href="#" class="d-none" id="focus-bottom"></a>
        

        2 - 收到新消息时:

        function getMessages (letter) {
          var div = $('#messages');
          $.get('msg_show.php', function(data){
            div.html(data);
            $('#focus-bottom').focus();
            $('#focus-box-message').focus(); / * FOCUS YOUR TEXTAREA * /
          });
        }
        
        setInterval(getMessages, 100);
        

        【讨论】:

          【解决方案7】:

          不必混合使用 jquery 和 javascript。像这样使用,

          function getMessages(letter) {
              var message=$('#messages');
              $.get('msg_show.php', function(data) {
                  message.html(data);
                  message.scrollTop(message[0].scrollHeight);
              });
          }
          
          setInterval(function() {
              getMessages("letter");
          }, 100)
          

          scrollTop() 放入get() 方法中。

          你也错过了getMessage方法调用中的一个参数..

          【讨论】:

          • 与问题没有直接关系,但反复使用$('#messages') 一遍又一遍地查询相同的元素会对性能产生负面影响——可能还会影响可读性。甚至可以在getMessages 函数之外选择元素。
          • 你是对的。我已经编辑了答案。但是在 getmessage 函数之外选择该元素没有任何意义。因为他需要在收到新消息后向下滚动到底部。所以它应该只在那个方法里面..
          【解决方案8】:

          我在实验的时候发现了这个非常简单的方法:将scrollTo设置为div的高度。

          var myDiv = document.getElementById("myDiv");
          window.scrollTo(0, myDiv.innerHeight);
          

          【讨论】:

            【解决方案9】:
                var l = document.getElementsByClassName("chatMessages").length;
                document.getElementsByClassName("chatMessages")[l-1].scrollIntoView();
            

            这应该可以工作

            【讨论】:

            • 假设您的包含聊天消息的聊天框不在视图中,那么这将滚动整个页面并将聊天框也显示在视图中。不是你想要的。
            【解决方案10】:

            由于我不是 js 大师,但我自己编写代码来检查用户是否处于底部。 如果用户位于底部,则聊天页面将自动滚动显示新消息。 如果用户向上滚动页面将不会自动滚动到底部..

            JS代码-

            var checkbottom;
            jQuery(function($) {
            $('.chat_screen').on('scroll', function() {
                var check = $(this).scrollTop() + $(this).innerHeight() >= $(this) 
            [0].scrollHeight;
                if(check) {
                   checkbottom = "bottom";
                }
                else {
                checkbottom = "nobottom";
                }
            })
            });
            window.setInterval(function(){
            if (checkbottom=="bottom") {
            var objDiv = document.getElementById("chat_con");
            objDiv.scrollTop = objDiv.scrollHeight;
            }
            }, 500);
            

            html代码-

            <div id="chat_con" class="chat_screen">
            </div>
            

            【讨论】:

              【解决方案11】:

              要滚动到消息框顶部的特定元素,请查看以下演示:

              https://jsfiddle.net/6smajv0t/

              function scrollToBottom(){
              	const messages = document.getElementById('messages');
              	const messagesid = document.getElementById('messagesid');  
              	messages.scrollTop = messagesid.offsetTop - 10;
              }
              
              scrollToBottom();
              setInterval(scrollToBottom, 1000);
              #messages {
                height: 200px;
                overflow-y: auto;
              }
              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
              <div id="messages">
                <div class="message">
                  Hello world1
                </div>
                <div class="message">
                  Hello world2
                </div>
                <div class="message">
                  Hello world3
                </div>
                <div class="message">
                  Hello world4
                </div>
                <div class="message">
                  Hello world5
                </div>
                <div class="message">
                  Hello world7
                </div>
                <div class="message">
                  Hello world8
                </div>
                <div class="message">
                  Hello world9
                </div>
                <div class="message" >
                  Hello world10
                </div>
                <div class="message">
                  Hello world11
                </div>
                <div class="message">
                  Hello world12
                </div>
                <div class="message">
                  Hello world13
                </div>
                <div class="message">
                  Hello world14
                </div>
                <div class="message">
                  Hello world15
                </div>
                <div class="message" id="messagesid">
                  Hello world16 here
                </div>
                <div class="message">
                  Hello world17
                </div>
                <div class="message">
                  Hello world18
                </div>
                <div class="message">
                  Hello world19
                </div>
                <div class="message">
                  Hello world20
                </div>
                <div class="message">
                  Hello world21
                </div>
                <div class="message">
                  Hello world22
                </div>
                <div class="message">
                  Hello world23
                </div>
                <div class="message">
                  Hello world24
                </div>
                <div class="message">
                  Hello world25
                </div>
                <div class="message">
                  Hello world26
                </div>
                <div class="message">
                  Hello world27
                </div>
                <div class="message">
                  Hello world28
                </div>
                <div class="message">
                  Hello world29
                </div>
                <div class="message">
                  Hello world30
                </div>
              </div>

              【讨论】:

                【解决方案12】:

                const messages = document.getElementById('messages');
                
                function appendMessage() {
                	const message = document.getElementsByClassName('message')[0];
                  const newMessage = message.cloneNode(true);
                  messages.appendChild(newMessage);
                }
                
                function getMessages() {
                	// Prior to getting your messages.
                  shouldScroll = messages.scrollTop + messages.clientHeight === messages.scrollHeight;
                  /*
                   * Get your messages, we'll just simulate it by appending a new one syncronously.
                   */
                  appendMessage();
                  // After getting your messages.
                  if (!shouldScroll) {
                    scrollToBottom();
                  }
                }
                
                function scrollToBottom() {
                  messages.scrollTop = messages.scrollHeight;
                }
                
                scrollToBottom();
                
                setInterval(getMessages, 100);
                #messages {
                  height: 200px;
                  overflow-y: auto;
                }
                <div id="messages">
                  <div class="message">
                    Hello world
                  </div>
                </div>

                【讨论】:

                  【解决方案13】:

                  我更喜欢使用 Vanilla JS

                  let chatWrapper = document.querySelector('#chat-messages');
                  chatWrapper.scrollTo(0, chatWrapper.offsetHeight );
                  

                  其中 element.scrollTo(x-coord, y-coord)

                  【讨论】:

                  • @AdamVýborný Lmao 是的,刚刚注意到。
                  • @AdamVýborný 这不是驳回答案的理由。今天仍然有人遇到同样的问题,也许您在 7 年前找到的解决方案不再被认为是合适的方法。
                  • @GustavoMaximo 我没有拒绝任何事情
                  【解决方案14】:

                  使用这个

                  function getMessages(letter) {
                    var div = $('#messages');
                    $.get('msg_show.php', function (data) {
                      div.html(data).animate({scrollTop: div.prop("scrollHeight")});
                      //use append() if msg_show.php returns single unread msg.
                    });
                  }
                  
                  setInterval(getMessages, 100);
                  

                  【讨论】:

                    猜你喜欢
                    • 2023-03-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-01-16
                    • 2010-10-18
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多