如何使用 JavaScript 同步滚动两个不同大小的框,使用一个作为参考
Posted
技术标签:
【中文标题】如何使用 JavaScript 同步滚动两个不同大小的框,使用一个作为参考【英文标题】:How do I synchronise scrolling of two different sized boxes using one as a reference using JavaScript 【发布时间】:2022-01-09 21:47:45 【问题描述】:我有两个盒子,一个比另一个小。小框包含与另一个相同的文本,但由于它更小,自动滚动需要更长的时间。我希望大框在小框结束的同时结束滚动。
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>
【问题讨论】:
不要使用setInterval
两次。相反,使用滚动百分比更新第二个,而不是仅使用相同的scrollTop
【参考方案1】:
不要使用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>
【讨论】:
非常感谢您。几天来我一直在寻找解决方案。 如果你也能解释一下数学,我将永远感激不尽:) @Zoli 哪个部分?我试图用变量名大量记录它? 确实需要很多时间。关键是要理解scrollTop
不必设置为scrollHeight
来一直滚动元素,它只需要设置为scrollHeight - clientHeight
并且您将其用作scrollTop
【参考方案2】:
使用百分比而不是滚动索引。制作几个辅助函数,它会更容易理解。看:
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>
【讨论】:
似乎对我不起作用??甚至没有动画滚动... @JuanMendes - 我明白了.. Chrome 有问题。我去看看。 非常感谢,这里的问题是我需要以他们不在同一页面上的方式来实现这个,主人用他的身高和速度发送一个播放信号,我需要将这些指标转换为与 master 匹配的毫秒数。 @Zoli - 这是怎么回事?发送信号以更新事件处理程序中的从站。 @Iwrestledabearonce。我正在通过firebase实时数据库尝试此操作,我将四舍五入的百分比与主人的高度一起保存。我需要使用这些指标来实现平滑滚动,但我不能使用四舍五入的百分比(我将使用它来检查它是否非常关闭,如果它是我将其重置为正确的百分比 - 仅当用户连接不良时)我需要某种公式,可以给我正确的毫秒传递给setInterval
。以上是关于如何使用 JavaScript 同步滚动两个不同大小的框,使用一个作为参考的主要内容,如果未能解决你的问题,请参考以下文章
C#两个datagridview分别绑定了相同结构的内容不同的DATATABLE,求两个datagridview的横纵滚动条同步滚动