javascript - Lås scroll när nytt innehåll läggs till ovanför och nedanför
Jag har en meteor.js-app som fungerar som ett nyhetsflöde, där trådar publiceras och folk kommenterar trådarna i realtid. Detta innebär att medan du tittar på ett inlägg kommer nya kommentarer att läggas till på inlägg ovanför och nedanför och nya trådar kommer att läggas till ovanför. Detta kommer att trycka ner det inlägg du fokuserar på och ut ur visningsfönstret, vilket aldrig är förväntat (om du inte redan har skrollat till toppen).
Vad är det bästa sättet att uppdatera scrollningen för att behålla samma visuella centrum när nytt innehåll läggs till?
Svar #1
Du kan prova det här tillvägagångssättet:
- spara
scrollTop-värdet; - lägg till innehållet först (dvs. lägg till ett nytt inlägg ovanför det som är markerat);
- lägg till höjden på det nya innehållet till värdet som sparades i steg 1;
- skrolla till det nya värdet.
Här är ett exempel:
function randomString() {
return Math.random().toString(36).substring(7);
}
$('#addAbove').on('click', function(e){
var newDiv = $('<li class="post">' + randomString() + '</li>');
var savedScrollTop = $('#content').scrollTop();
$('#content').prepend(newDiv);
$('#content').scrollTop(savedScrollTop + newDiv.height());
});
$('#addBelow').on('click', function(e){
var newDiv = $('<li class="post">' + randomString() + '</li>');
$('#content').append(newDiv);
});#content {
height: 100px;
overflow-y: scroll;
}
.post {
height: 40px;
}<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="content">
<li class="post">u9tv190be29</li>
<li class="post">dgdr8gp66rp</li>
<li class="post">93vfntdquxr</li>
</ul>
<button id="addAbove">Add Above</button>
<button id="addBelow">Add Below</button>Att lägga till innehåll under den nuvarande vyporten borde inte kräva justering.
Här är ett blogginlägg som beskriver en liknande metod, och en liknande fråga på SO.
Svar #2
Jag föreslår att du gör på detta sätt: när ett nytt objekt ska läggas till kontrollerar du om du är högst upp, om så är fallet, lägger du bara till det nya objektet.
Om inte, får du det befintliga top/height för din item-behållare, lägger till det nya objektet, får item-behållarens höjd en andra gång och uppdaterar sedan scroll top.
Här är ett enkelt exempel på hur man kan göra, genom att lägga till både längst upp och längst ner (förresten, längst ner behövs ingen scrollkompensation).
function addItem (totop) {
var msgdiv = document.getElementById('items');
var attop = scrollAtTop(msgdiv);
var prevtop = parseInt(msgdiv.scrollHeight - msgdiv.scrollTop);
if (totop) {
msgdiv.innerHTML = 'Long long content ' + (tempCounter++) + '!<br/>' + msgdiv.innerHTML;
if (!attop) {
updateScroll(msgdiv, parseInt(msgdiv.scrollHeight) - prevtop);
}
} else {
msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
}
}
var tempCounter = 10;
function updateScroll(el, top){
el.scrollTop = top;
}
function scrollAtTop(el){
return (el.scrollTop == 0);
}html, body { height:100%; margin:0; padding:0; }
.items{
display: inline-block;
width: 300px;
height: 220px;
border: 1px solid black;
overflow: auto;
}
button { width: 15%; height: 44px; margin: 20px; vertical-align: top; }<div class="items" id="items">
Long long content 9!<br/>
Long long content 8!<br/>
Long long content 7!<br/>
Long long content 6!<br/>
Long long content 5!<br/>
Long long content 4!<br/>
Long long content 3!<br/>
Long long content 2!<br/>
Long long content 1!<br/>
</div>
<button onclick="addItem(true);">Add 2 top</button><button onclick="addItem(false);">Add 2 bottom</button>