Я создаю чат, используя запросы Ajax, и без особого успеха пытаюсь заставить div сообщений прокручиваться вниз.
Я оборачиваю все в этот div:
#scroll {
height:400px;
overflow:scroll;
}
Есть ли способ по умолчанию прокручивать его вниз с помощью JS?
Есть ли способ сохранить его прокруткой вниз после запроса ajax?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот что я использую на своем сайте:
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
@PaulDinh: Я только что изучил это, и есть проблема с IE7 и ниже, используя scrollHeight. Кажется, есть обходной путь для IE7 здесь.
почему бы не scrollTopMax вместо scrollHeight?
Это не работает, когда я динамически добавляю изображения :(
«Современный» способ - использовать Element.scrollIntoView () - developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoV iew
можете ли вы использовать var element = document.getElementById ("elementToSelect"); element.scrollIntoView ();
Это не сработало для меня. Если у вас есть запрос, используйте @andsien .. Обратите внимание, что альтернативный анимированный вариант может иметь неотредактированное поведение с блокировкой полосы прокрутки в Safari <= 14.0.1 (последняя версия)
Это намного проще, если вы используете jQuery scrollTop:
$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
вам нужно [0], чтобы получить элемент dom из элемента jquery, чтобы получить scrollHeight
Без повторения: $("#mydiv").scrollTop(function() { return this.scrollHeight; });
используя jQuery animate:
$('#DebugContainer').stop().animate({
scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
Обратите внимание, как в этом ответе используется .останавливаться(), который предотвращает проблемы с несколькими анимациями.
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));
Работает с jQuery 1.6
Если вы не хотите полагаться на scrollHeight, вам поможет следующий код:
$('#scroll').scrollTop(1000000);
похоже на взлом. что означает число 1000000?
небольшое дополнение: прокручивается, только если последняя строка уже видна. если прокрутить немного, оставляет содержимое там, где оно есть (внимание: не тестировалось с разными размерами шрифта. Это может потребовать некоторых корректировок внутри "> = сравнение"):
var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);
// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!
// doScroll is true, if we the bottom line is already visible
if ( doScroll) objDiv.scrollTop = objDiv.scrollHeight;
Просто как бонусный фрагмент. Я использую angular и пытался прокрутить цепочку сообщений вниз, когда пользователь выбирал разные разговоры с пользователями. Чтобы убедиться, что прокрутка работает после того, как новые данные были загружены в div с помощью ng-repeat для сообщений, просто оберните фрагмент прокрутки в тайм-аут.
$timeout(function(){
var messageThread = document.getElementById('message-thread-div-id');
messageThread.scrollTop = messageThread.scrollHeight;
},0)
Это гарантирует, что событие прокрутки запускается после того, как данные были вставлены в DOM.
Я подозреваю, что $ scope. $ Apply (обратный вызов) будет работать так же хорошо, как это заставит дайджест и переоценку представления.
Спасибо! Мне действительно было интересно, почему я не могу заставить его работать, и проблема заключалась в тайм-ауте $.
@Wayferer тот же setTimeout(function() { ... }, n)
Более новый метод, который работает на все текущие браузеры:
this.scrollIntoView(false);
Это должен быть принятый ответ, поскольку старые методы больше не работают.
Это было бы так, если бы "this" - это что-то в div, которое можно прокрутить до
Метод scrollIntoView запускается для дочернего элемента внутри родительского контейнера. Итак, как использовать его, чтобы: прокрутить родителя вниз (как задано в исходном вопросе).
Можно использовать scrollIntoView({ behavior: "smooth", block: "end" });
Посмотрите, какие браузеры здесь поддерживаются caniuse.com/?search=scrollIntoView
Используя jQuery, scrollTop используется для установки вертикального положения полосы прокрутки для любого заданного элемента. есть также красивый плагин jquery scrollTo, используемый для прокрутки с анимацией и различными параметрами (демонстрации)
var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;
если вы хотите использовать Метод анимации jQuery для добавления анимации при прокрутке вниз, проверьте следующий фрагмент:
var myDiv = $("#div_id").get(0);
myDiv.animate({
scrollTop: myDiv.scrollHeight
}, 500);
Это позволит вам прокручивать страницу вниз по высоте документа.
$('html, body').animate({scrollTop:$(document).height()}, 1000);
Нашел это действительно полезным, спасибо.
Для разработчиков Angular 1.X:
angular.module('myApp').controller('myController', ['$scope', '$document',
function($scope, $document) {
var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;
}
]);
Просто потому, что упаковка элементов jQuery по сравнению с элементами HTML DOM немного сбивает с толку с angular.
Также для приложения чата я обнаружил, что выполнение этого назначения после загрузки ваших чатов может быть полезным, вам также может потребоваться короткое время ожидания.
Я столкнулся с той же проблемой, но с дополнительным ограничением: у меня не было контроля над кодом, добавляющим новые элементы в контейнер прокрутки. Ни один из примеров, которые я здесь нашел, не позволял мне этого делать. Вот решение, к которому я пришел.
Он использует Mutation Observers (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver), что позволяет использовать его только в современных браузерах (хотя полифиллы существуют)
Итак, в основном код делает именно это:
var scrollContainer = document.getElementById("myId");
// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {
// Compute sum of the heights of added Nodes
var newNodesHeight = mutations.reduce(function(sum, mutation) {
return sum + [].slice.call(mutation.addedNodes)
.map(function (node) { return node.scrollHeight || 0; })
.reduce(function(sum, height) {return sum + height});
}, 0);
// Scroll to bottom if it was already scrolled to bottom
if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
scrollContainer.scrollTop = scrollContainer.scrollHeight;
}
});
// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});
Я сделал скрипку, чтобы продемонстрировать концепцию: https://jsfiddle.net/j17r4bnk/
как получить динамический идентификатор? как в <div class = "abc"><div data-bind=attr : {'id': myId } ></div></div> В этом коде myId - это переменная. Как я могу получить доступ к этому идентификатору в скрипте.
Я не совсем уверен, что понимаю ваш вопрос. В моем примере «myId» - это идентификатор контейнера прокрутки. Вы хотите создать более одной области, в которой пользователь может прокручивать?
Вы можете попробовать приведенный ниже код:
function scrollToBottom (id) {
var div = document.getElementById(id);
div.scrollTop = div.scrollHeight - div.clientHeight;
}
Чтобы выполнить прокрутку гладкий с помощью JQuery:
function scrollSmoothToBottom (id) {
var div = document.getElementById(id);
$('#' + id).animate({
scrollTop: div.scrollHeight - div.clientHeight
}, 500);
}
См. пример на JSFiddle
Вот почему это работает:
Ссылка: scrollTop, scrollHeight, clientHeight
это действительно правильный ответ, картинка действительно полезна
Вы также можете, используя jQuery, прикрепить анимацию к html,body документа через:
$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);
что приведет к плавной прокрутке вверху div с идентификатором «div-id».
Javascript или jquery:
var scroll = document.getElementById('messages');
scroll.scrollTop = scroll.scrollHeight;
scroll.animate({scrollTop: scroll.scrollHeight});
CSS:
.messages
{
height: 100%;
overflow: auto;
}
Я знаю, что это старый вопрос, но ни одно из этих решений для меня не помогло. В итоге я использовал offset (). Top для получения желаемых результатов. Вот что я использовал для мягкого прокрутите экран вниз последнего сообщения в моем приложении чата:
$("#html, body").stop().animate({
scrollTop: $("#last-message").offset().top
}, 2000);
Надеюсь, это поможет кому-то другому.
Javascript:
document.getElementById('messages').scrollIntoView(false);
Прокручивает до последней строки присутствующего содержимого.
Очень простой способ - установить scroll to на высоту div.
var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
Прокрутите до последнего элемента внутри div:
myDiv.scrollTop = myDiv.lastChild.offsetTop
гладкий прокрутка с помощью Javascript:
document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });
использовать :
var element= $('element');
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.scrollTop(maxScrollTop);
или проверьте прокрутку вниз:
var element = $(element);
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.on('scroll', function() {
if ( element.scrollTop() >= maxScrollTop ) {
alert('scroll to bottom');
}
});
измените scrollTopMax на var maxScrollTop = element [0] .scrollHeight - element.outerHeight ();
Если это делается для прокрутки окна чата вниз, выполните следующие действия.
Идея прокрутки к конкретному div в чате заключалась в следующем
1) Каждый div чата, состоящий из Person, time и message, запускается в цикле for с классом chatContentbox.
2) querySelectorAll находит все такие массивы. Это может быть 400 узлов (400 чатов)
3) перейти к последнему
4) scrollIntoView ()
let lastChatBox = document.querySelectorAll('.chatContentBox');
lastChatBox = lastChatBox[lastChatBox.length-1];
lastChatBox.scrollIntoView();
Иногда самое простое - лучшее решение: Я не знаю, поможет ли это, мне тоже помогло прокрутить его, когда я когда-либо хотел. Чем выше "y =", тем больше он прокручивается вниз, и, конечно же, "0" означает верх, поэтому, например, "1000" может быть низом, или "2000", или "3000" и так далее, в зависимости от того, как долго вы страница есть. Обычно это работает в кнопке с onclick или onmouseover.
window.scrollTo(x=0,y=150);
Установите расстояние от верха прокручиваемого элемента как общую высоту элемента.
const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight
В моем приложении Angular 6 я только что сделал это:
postMessage() {
// post functions here
let history = document.getElementById('history')
let interval
interval = setInterval(function() {
history.scrollTop = history.scrollHeight
clearInterval(interval)
}, 1)
}
Функция clearInterval (interval) остановит таймер, чтобы разрешить ручную прокрутку вверх / вниз.
Вы можете использовать метод scrollIntoView HTML DOM следующим образом:
var element = document.getElementById("scroll");
element.scrollIntoView();
Мой сценарий: у меня был список строк, в который мне нужно было добавить строку, заданную пользователем, и автоматически прокрутить до конца списка. У меня была фиксированная высота отображения списка, после чего он должен переполняться.
Я попробовал ответить @Jeremy Ruten, он сработал, но прокручивался до (n-1) -го элемента. Если кто-то сталкивается с этой проблемой, вы можете использовать обходной путь метода setTimeOut(). Вам необходимо изменить код, как показано ниже:
setTimeout(() => {
var objDiv = document.getElementById('div_id');
objDiv.scrollTop = objDiv.scrollHeight
}, 0)
Вот созданная мной ссылка на StcakBlitz, которая показывает проблему и ее решение: https://stackblitz.com/edit/angular-ivy-x9esw8
с setTimeout () все работает нормально. Работал с angular 9. День спас.
Рад помочь :)
Как и вы, я создаю приложение для чата и хочу, чтобы последнее сообщение отображалось в поле зрения. В конечном итоге это сработало для меня:
//get the div that contains all the messages
let div = document.getElementById('message-container');
//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });
Я использую разницу между координатой Y первого элемента div и координатой Y выбранного элемента div. Вот код JavaScript / JQuery и HTML:
function scrollTo(event){
// In my proof of concept, I had a few <button>s with value
// attributes containing strings with id selector expressions
// like "#item1".
let selectItem = $($(event.target).attr('value'));
let selectedDivTop = selectItem.offset().top;
let scrollingDiv = selectItem.parent();
let firstItem = scrollingDiv.children('div').first();
let firstItemTop = firstItem.offset().top;
let newScrollValue = selectedDivTop - firstItemTop;
scrollingDiv.scrollTop(newScrollValue);
}<div id = "scrolling" style = "height: 2rem; overflow-y: scroll">
<div id = "item1">One</div>
<div id = "item2">Two</div>
<div id = "item3">Three</div>
<div id = "item4">Four</div>
<div id = "item5">Five</div>
</div>Вы можете использовать метод Элемент.scrollTo ().
Его можно анимировать с помощью встроенной анимации браузера / ОС, поэтому он очень плавный.
function scrollToBottom() {
const scrollContainer = document.getElementById('container');
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
left: 0,
behavior: 'smooth'
});
}
// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
contentInnerHtml += `<div class = "card mb-2"><div class = "card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;.overflow-y-scroll {
overflow-y: scroll;
}<link href = "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel = "stylesheet"/>
<div class = "d-flex flex-column vh-100">
<div id = "container" class = "overflow-y-scroll flex-grow-1"></div>
<div>
<button class = "btn btn-primary" onclick = "scrollToBottom()">Scroll to bottom</button>
</div>
</div>альтернативное решение
function scrollToBottom(element) {
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
подходит ли этот метод для всех браузеров?