如何使用 JavaScript 以一个作为参考来同步两个不同大小的框的滚动

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

我有两个盒子,一个比另一个小。小框包含与另一个相同的文本,但由于它更小,自动滚动需要更长的时间。我希望大框在小框结束的同时结束滚动。

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>

使用百分比而不是滚动索引。做几个辅助函数,它会更容易理解。看:

let masterElement = document.getElementById("master-box");
let slaveElement = document.getElementById("slave-box");

// Scroll to a percentage of the vertical height
function scrollToPct(element, pct){
  var scroll = (element.scrollHeight - element.clientHeight) / 100 * pct;
  element.scrollTo({ top: scroll, behavior: 'smooth' });
}

// Get the percentage of vertical scroll
function getScrollPct(element){
  return element.scrollTop / (element.scrollHeight - element.clientHeight) * 100;
}

// Listen to the mastre element and update the slave element accordingly
masterElement.addEventListener('scroll', function(){
  var scroll_pct = getScrollPct(this);
  scrollToPct(slaveElement, scroll_pct);
});

// turn on the autoscroll
setInterval(function(){
  var scroll_pct = getScrollPct(masterElement);
  scrollToPct(masterElement, scroll_pct + 5);
}, 10);
.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>

不要使用 setInterval 两次。相反,使用滚动百分比而不是仅使用相同的 scrollTop 来更新第二个。

此外,将行为设置为平滑会导致动画 运行,这可能会干扰您的滚动命令。

最后,您需要考虑 scrollHeight 和 clientHeight。

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>