Search code examples
javascripthtmlmathautoscroll

How do I synchronise scrolling of two different sized boxes using one as a reference using JavaScript


I have two boxes, one is smaller then the other. The small box contains the same text as the other, but since it's smaller auto scrolling takes a longer time. I would like the big box to end scrolling the same time the small box ends.

let stepSize = 0.5;
let masterSpeed = 50;
let masterElement = document.getElementById("master-box");
let slaveElement = document.getElementById("slave-box");

var scroll = 0;

window.setInterval(function(){ 
  if(masterElement.scrollTop > scroll)
  scroll = masterElement.scrollTop;
  masterElement.scrollTo({ top: scroll, behavior: 'smooth' })
  scroll += 1; 
}, masterSpeed); //THIS WILL RUN IN EVERY 50 MILISECONDS

// Match slave speed to master speed
let masterDistance = masterElement.scrollHeight - masterElement.clientHeight;
let masterScrollTime = masterDistance / masterSpeed;
let syncedSpeed = masterDistance / masterScrollTime;

window.setInterval(function(){ 
  if(slaveElement.scrollTop > scroll)
  scroll = slaveElement.scrollTop;
  slaveElement.scrollTo({ top: scroll, behavior: 'smooth' })
  scroll += 1; 
}, syncedSpeed); //THIS WILL RUN IN EVERY 50 MILISECONDS
.container {
  display: flex;
}
span {
  display: block;
  height : 3px;
  background: red;
}
.box1{
  width: 100px;
  height: 200px;
  overflow-y: auto;
  border: 2px solid blue;
  margin: 10px;
}
.box2{
  width: 200px;
  height: 300px;
  overflow-y: auto;
  border: 2px solid blue;
  margin: 10px;
}
<div class="container">
<div class="box1" id="master-box">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!<span></span></div>
<div class="box2" id="slave-box">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!<span></span></div>
</div>


Solution

  • Do not use setInterval twice. Instead, update the second one using a percentage of scroll instead of just using the same scrollTop.

    Also, setting the behavior to smooth was causing animations to run which could interfere with your scrolling commands.

    Lastly, you need to take the scrollHeight and clientHeight into account.

    const masterSpeed = 50;
    const stepSize = 10;
    const masterElement = document.getElementById("master-box");
    const slaveElement = document.getElementById("slave-box");
    
    const masterScrollHeight = masterElement.scrollHeight;
    const slaveScrollHeight = slaveElement.scrollHeight;
    const masterClientHeight = masterElement.clientHeight;
    const slaveClientHeight = slaveElement.clientHeight;
    
    const masterHeight = masterScrollHeight - masterClientHeight;
    const slaveHeight = slaveScrollHeight - slaveClientHeight;
    /*
    console.log({
      masterScrollHeight,
      slaveScrollHeight,
      masterClientHeight,
      slaveClientHeight,
      masterHeight,
      slaveHeight
    });
    */
    let interval = window.setInterval(function() {
      const currentMasterScrollTop = masterElement.scrollTop;
      const newMasterScrollTop = currentMasterScrollTop + stepSize;
      if (newMasterScrollTop > masterHeight) {
    
        window.clearInterval(interval);
        interval = null;
      }
    
      const percentageMasterDone = newMasterScrollTop / masterHeight;
      const newSlaveScrollTop = Math.ceil(percentageMasterDone * slaveHeight);
      /*
        console.log({
          currentMasterScrollTop,
          newMasterScrollTop,
          percentageMasterDone,
          newMasterScrollTop,
          newSlaveScrollTop
        });
        */
      masterElement.scrollTo({
        top: newMasterScrollTop
      });
      slaveElement.scrollTo({
        top: newSlaveScrollTop
      })
    
    }, masterSpeed); //THIS WILL RUN IN EVERY 50 MILISECONDS
    .container {
      display: flex;
    }
    
    span {
      display: block;
      height: 3px;
      background: red;
    }
    
    .box1 {
      width: 100px;
      height: 200px;
      overflow-y: auto;
      border: 2px solid blue;
      margin: 10px;
    }
    
    .box2 {
      width: 200px;
      height: 300px;
      overflow-y: auto;
      border: 2px solid blue;
      margin: 10px;
    }
    <div class="container">
      <div class="box1" id="master-box">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur,
        adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur
        sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam
        autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!<span></span></div>
      <div class="box2" id="slave-box">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur,
        adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur
        sequi harum sunt adipisci aperiam autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Qui, aspernatur sequi harum sunt adipisci aperiam
        autem perspiciatis quidem delectus corporis nulla modi sit id, odit minus. Natus tenetur iusto temporibus!<span></span></div>
    </div>