Búsqueda de sitios web

javascript - Bloquear el desplazamiento a medida que se agrega nuevo contenido arriba y abajo


Tengo una aplicación meteor.js que funciona como un feed de noticias, con hilos que se publican y personas comentando en los hilos en tiempo real. Esto significa que mientras estás viendo una publicación, se agregarán nuevos comentarios a las publicaciones de arriba y de abajo, y se agregarán nuevos hilos arriba. Esto empujará la publicación en la que te estás enfocando hacia abajo y fuera del área visible, lo cual nunca se espera (a menos que ya estés desplazado hasta la parte superior).

¿Cuál es la mejor manera de actualizar el desplazamiento para mantener el mismo centro visual a medida que se agrega nuevo contenido?

Respuesta #1

Podrías probar este enfoque:

  1. guardar el valor de scrollTop;
  2. anteponer el contenido (es decir, agregar una nueva publicación encima de la que está enfocada);
  3. suma la altura del nuevo contenido al valor guardado en el paso 1;
  4. desplázate hasta el nuevo valor.

Aquí hay un ejemplo:

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>

Agregar contenido debajo del área visible actual no debería requerir ajustes.

Aquí hay una publicación de blog que describe un enfoque similar y una pregunta similar en SO.

Respuesta #2

Te sugiero que hagas así: cuando se vaya a añadir un nuevo elemento, comprueba si estás en la parte superior; si es así, entonces simplemente añade el nuevo elemento.

Si no, obtienes la parte superior/altura existente de tu contenedor de elementos, agregas el nuevo elemento, obtienes la altura del contenedor de elementos una segunda vez y luego actualizas el desplazamiento superior.

Aquí hay un ejemplo simple de cómo se puede hacer, agregando tanto en la parte superior como en la inferior (por cierto, en la parte inferior no se necesita compensación de desplazamiento).

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>