我希望有 2 个 div 大小为特定宽度(即 500 像素)。一个在另一个之上,水平对齐。
顶部框应隐藏其滚动条,底部应显示滚动条,当用户滚动时,我希望顶部框的偏移量更改为底部框的值。因此,当底部 DIV 水平滚动时,顶部 DIV 似乎也在同步滚动。
如果它使过程更容易,我很高兴在 Jquery 中执行此操作。
$('#bottom').on('scroll', function () {
$('#top').scrollTop($(this).scrollTop());
});
在这里,我们尽其所能使用 .scrollTop()
,从带有滚动条的元素中获取 scrollTop
值,并为其他元素设置 scrollTop
以同步它们的滚动位置:http://api.jquery.com/scrollTop
这假定底部元素的 ID 为 bottom
,顶部元素的 ID 为 top
。
您可以使用 CSS 隐藏 top
元素的滚动条:
#top {
overflow : hidden;
}
这是一个演示:http://jsfiddle.net/sgcer/1884/
我想我从来没有真正有理由这样做,但它看起来很酷。
我知道这是一个旧线程,但也许这会对某人有所帮助。如果您需要双向同步滚动,仅处理两个容器的滚动事件并设置滚动值是不够的,因为滚动事件进入循环并且滚动不平滑(尝试垂直滚动鼠标滚轮 Hightom 给出的示例)。
这是一个如何检查是否已经在同步滚动的示例:
var isSyncingLeftScroll = false; var isSyncingRightScroll = false; var leftDiv = document.getElementById('left'); var rightDiv = document.getElementById('right'); leftDiv.onscroll = function() { if (!isSyncingLeftScroll) { isSyncingRightScroll = true; rightDiv.scrollTop = this.scrollTop; } isSyncingLeftScroll = false; } rightDiv.onscroll = function() { if (!isSyncingRightScroll) { isSyncingLeftScroll = true; leftDiv.scrollTop = this.scrollTop; } isSyncingRightScroll = false; } .container { 宽度:200px;高度:500px;溢出-y:自动; } .leftContainer { 浮动:左; } .rightContainer { 浮动:对; }
这是fiddle。
我一直在寻找双向解决方案,感谢大家,您的贡献帮助我做到了这一点:
$('#cells').on('scroll', function () {
$('#hours').scrollTop($(this).scrollTop());
$('#days').scrollLeft($(this).scrollLeft());});
参见 JSFiddle:https://jsfiddle.net/sgcer/1274/
希望有一天它对某人有所帮助:-)
好的,所以我评估了这里提供的所有选项,它们都有一种或另一种形式的限制:
接受的答案存在使用鼠标滚轮的已知问题。
下一个最高赞成票没有滚轮问题,但仅适用于两个已知元素。如果您需要更多元素,则它是不可扩展的。
唯一显示出希望的解决方案是 Lacho 的,但代码中存在已知的元素引用,这些引用未包含在代码段中。从好的方面来说,它具有性能所需的结构,而且它在 TypeScript 中。
我利用它创建了一个可重用的版本,它可以处理无限数量的元素,并且不需要 JQuery。
function scrollSync(selector) {
let active = null;
document.querySelectorAll(selector).forEach(function(element) {
element.addEventListener("mouseenter", function(e) {
active = e.target;
});
element.addEventListener("scroll", function(e) {
if (e.target !== active) return;
document.querySelectorAll(selector).forEach(function(target) {
if (active === target) return;
target.scrollTop = active.scrollTop;
target.scrollLeft = active.scrollLeft;
});
});
});
}
//RWM: Call the function on the elements you need synced.
scrollSync(".scrollSync");
您可以在此处查看 JSFiddle:http://jsfiddle.net/gLa2ndur/3。您可以看到它同时使用了水平和垂直滚动示例。
唯一已知的限制是它可能不适用于不同大小的 div。如果您的用例认为有必要(我的没有),我相信有人可以将 Andrew's work 纳入其中。
我希望这对某人有帮助!
防止这种循环问题并实现平滑滚动的另一种解决方案。这确保只有焦点元素获得滚动事件。
let activePre: HTMLPreElement = null;
document.querySelectorAll(".scrollable-pre").forEach(function(pre: HTMLPreElement) {
pre.addEventListener("mouseenter", function(e: MouseEvent) {
let pre = e.target as HTMLPreElement;
activePre = pre;
});
pre.addEventListener("scroll", function(e: MouseEvent) {
let pre = e.target as HTMLPreElement;
if (activePre !== pre) {
return;
}
if (pre !== versionBasePre) {
versionBasePre.scrollTop = pre.scrollTop;
versionBasePre.scrollLeft = pre.scrollLeft;
}
if (pre !== versionCurrentPre) {
versionCurrentPre.scrollTop = pre.scrollTop;
versionCurrentPre.scrollLeft = pre.scrollLeft;
}
});
});
感谢上面的答案,我制作了一个适合我的混合解决方案:
var isLeftScrollTopCalled = false;
$('#leftElement').scroll(function (e) {
if (isRightScrollTopCalled) {
return isRightScrollTopCalled = false;
}
$('#rightElement').scrollTop($(this).scrollTop());
isLeftScrollTopCalled = true;
});
var isRightScrollTopCalled = false;
$('#rightElement').scroll(function (e) {
if (isLeftScrollTopCalled) {
return isLeftScrollTopCalled = false;
}
$('#leftElement').scrollTop($(this).scrollTop());
isRightScrollTopCalled = true;
});
我注意到他的问题已经很老了,但我认为我可以留下一个比使用计时器更好的 jQuery 实现。在这里,我使用两个事件侦听器,就像以前使用的解决方案一样,但是,这将使用比例/百分比来同步两个不同大小的 div 框的滚动。您可以应用相同的知识来获取滚动条到 Vanilla JS 解决方案的位置。这将使两个 div 之间的滚动更加平滑。
/** Scroll sync between editor and preview **/
// Locks so that only one pane is in control of scroll sync
var eScroll = false;
var pScroll = false;
// Set the listener to scroll
this.edit.on('scroll', function() {
if(eScroll) { // Lock the editor pane
eScroll = false;
return;
}
pScroll = true; // Enable the preview scroll
// Set elements to variables
let current = self.edit.get(0);
let other = self.preview.get(0);
// Calculate the position of scroll position based on percentage
let percentage = current.scrollTop / (current.scrollHeight - current.offsetHeight);
// Set the scroll position on the other pane
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
});
this.preview.on('scroll', function() {
if(pScroll) { // Lock the preview pane
pScroll = false;
return;
}
eScroll = true; // Enable the editor scroll
// Set elements to variables
let current = self.preview.get(0);
let other = self.edit.get(0);
// Calculate the position of scroll position based on percentage
let percentage = current.scrollTop / (current.scrollHeight - current.offsetHeight);
// Set the scroll position on the other pane
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
});
scrollTop
替换为scrollLeft
?scrollLeft
而不是scrollTop
:jsfiddle.net/sgcer/1#bottom
的overflow
实际上应该是overflow-y
,以避免在带有滚动控件的 div 底部获得 x-scrollbar。