自动向下滚动聊天 div

Posted

技术标签:

【中文标题】自动向下滚动聊天 div【英文标题】:Automatically scroll down chat 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')(注意缺少的 #)。 对不起,我实际上没有#。 【参考方案1】:

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

scrollHeight:容器总大小。 scrollTop: 用户滚动的数量。 clientHeight:用户看到的容器数量。

什么时候应该滚动?

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

以编程方式:

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);

【讨论】:

以上是关于自动向下滚动聊天 div的主要内容,如果未能解决你的问题,请参考以下文章

在设定的时间向下滚动聊天,但在用户交互时停用

如何让用户能够在受限功能后自动向下滚动

让DIV的滚动条自动滚动到最底部 - 3种方法

AJAX 聊天,自动滚动窗口

打开聊天Flutter时如何向下滚动聊天列表视图

滚动时显示和隐藏 Div