创建无缝嵌套滚动翻转
Creating Seamless nested scroll rollover
我正在尝试创建一系列 window 大小的 div,内部 div 的大小可变 > window。问题是它需要像没有嵌套的 div 一样滚动。
简而言之我想要这个:
css{
block{ height:100wh; }
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="block">
<div class="innerBlockLarge"></div>
</div>
<div class="block">
<div class="innerBlockSmall"></div>
</div>
https://jsfiddle.net/cbuh8psd/
像这样
css{
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="innerBlockLarge"></div>
<div class="innerBlockSmall"></div>
https://jsfiddle.net/t6zrvo7u/1/
不幸的是,滚动 "Focus" 是由 hover
在可滚动元素上滚动触发的。在这种情况下,这是一种不良行为。
我目前知道有 2 种可能的解决方案。
通过 javascript 手动分配卷轴 "Focus"。 (最优)
完全覆盖默认 HTML 滚动 javascript,因为
例如库 ISCROLL5.
(好的,如果性能影响很小的话)
不幸的是,在查看了 developer.mozilla 的 HTML5 文档后,我还没有 运行 通过任何方式 "Focus" 通过 javascript 滚动到一个元素.
至于选项 2:ISCROLL5 对超过 ~15-20 个滚动 div 的性能造成了不良影响。
我希望我在这里遗漏了一些东西,任何解决方案、修复或建议都将不胜感激。
我没有知道你为什么要这样做,但我能想到的实现你想要的效果的唯一方法是重新创建滚动条,不过好消息是,这不需要以失去您的本土体验为代价。
遗憾的是,我不记得我为哪个项目编写了这段代码,尽管实现此目的的一种方法是让自己成为一个滚动条组件。这个滚动条组件确实会提供一个伪造的滚动条,但会提供一个类似本机的界面。那么,你是怎么做到的?
- 您可以通过计算有和没有
overflow: scroll
的元素之间的差异来确定滚动条的宽度。设为 scrollWidth
- 您创建一个
<div>
,overflow: auto
,宽度 scrollWidth
,position: fixed
,它位于 body 的右侧。设 scrollTop
属性 为 scrollPosition
.
- 在元素中添加另一个
<div>
,宽度为 0
(这至少在 Chrome 中有效,检查其他浏览器是否有不同的处理方式)并让高度为 documentLength
.
- 现在,您可以通过任意设置
documentLength
和 scrollPosition
来完全控制滚动条。在您的情况下,您可以将 documentLength
设置为每个元素的组合滚动高度,并根据这些节点中的相对 scrollTop
设置 scrollPosition
。
这个概念(不是实现)的一个非常基本的演示可以在这个 jsfiddle 中找到(注意滚动条的 width
在这种情况下固定为 20px
并且没有任何动态代码)。
此解决方案允许滚动整个文档,同时保持使用鼠标滚动每个嵌套 div 的可能性。希望我理解正确。
这只是一个概念,它不会阻止嵌套元素随window一起滚动。但是可以改进。
Array.prototype.slice.call( document.getElementsByClassName('sbRemover') )
.forEach(function (div) {
var scroll = 0,
mousedown = false,
mouseBtnHandler = function (e) {
mousedown = e.type == 'mousedown';
}
div.addEventListener('scroll', function (e) {
// Change of div's scrollTop. Negative when scrolling down
var diff = scroll - e.target.scrollTop;
// Save new scroll value to be able to compare with it later
scroll = e.target.scrollTop;
// Do nothing when div is scrolled by dragging the scrollbar
if (!mousedown) {
// Scroll the window to the same amount of pixels the div was scrolled
window.scrollTo(window.pageXOffset, window.pageYOffset - diff);
}
});
div.addEventListener('mouseup', mouseBtnHandler);
div.addEventListener('mousedown', mouseBtnHandler);
});
body, div {
margin: 0;
padding: 0;
}
.block{
position: relative;
width:100vw;
height:100vh;
overflow: hidden;
z-index: 1;
opacity: 100;
}
.sbRemover{
width:100%;
height:100%;
padding-right:15px;
overflow: auto;
}
.largeContent{
height:225vh;
}
.smallContent{
height:100vh;
}
<div id="simpleCanvas">
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div id="ok" class="largeContent" style="background-image: url('http://silviahartmann.com/background-tile-art/images/grey-repeating-background-8.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://a1star.com/images/star--background-seamless-repeating9.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://people.stfx.ca/x2011/x2011ane/info102/assignment1/11500341-abstract-colorful-repeating-background.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
</div>
我正在尝试创建一系列 window 大小的 div,内部 div 的大小可变 > window。问题是它需要像没有嵌套的 div 一样滚动。
简而言之我想要这个:
css{
block{ height:100wh; }
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="block">
<div class="innerBlockLarge"></div>
</div>
<div class="block">
<div class="innerBlockSmall"></div>
</div>
https://jsfiddle.net/cbuh8psd/
像这样
css{
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="innerBlockLarge"></div>
<div class="innerBlockSmall"></div>
https://jsfiddle.net/t6zrvo7u/1/
不幸的是,滚动 "Focus" 是由 hover
在可滚动元素上滚动触发的。在这种情况下,这是一种不良行为。
我目前知道有 2 种可能的解决方案。
通过 javascript 手动分配卷轴 "Focus"。 (最优)
完全覆盖默认 HTML 滚动 javascript,因为 例如库 ISCROLL5.
(好的,如果性能影响很小的话)
不幸的是,在查看了 developer.mozilla 的 HTML5 文档后,我还没有 运行 通过任何方式 "Focus" 通过 javascript 滚动到一个元素.
至于选项 2:ISCROLL5 对超过 ~15-20 个滚动 div 的性能造成了不良影响。
我希望我在这里遗漏了一些东西,任何解决方案、修复或建议都将不胜感激。
我没有知道你为什么要这样做,但我能想到的实现你想要的效果的唯一方法是重新创建滚动条,不过好消息是,这不需要以失去您的本土体验为代价。
遗憾的是,我不记得我为哪个项目编写了这段代码,尽管实现此目的的一种方法是让自己成为一个滚动条组件。这个滚动条组件确实会提供一个伪造的滚动条,但会提供一个类似本机的界面。那么,你是怎么做到的?
- 您可以通过计算有和没有
overflow: scroll
的元素之间的差异来确定滚动条的宽度。设为scrollWidth
- 您创建一个
<div>
,overflow: auto
,宽度scrollWidth
,position: fixed
,它位于 body 的右侧。设scrollTop
属性 为scrollPosition
. - 在元素中添加另一个
<div>
,宽度为0
(这至少在 Chrome 中有效,检查其他浏览器是否有不同的处理方式)并让高度为documentLength
. - 现在,您可以通过任意设置
documentLength
和scrollPosition
来完全控制滚动条。在您的情况下,您可以将documentLength
设置为每个元素的组合滚动高度,并根据这些节点中的相对scrollTop
设置scrollPosition
。
这个概念(不是实现)的一个非常基本的演示可以在这个 jsfiddle 中找到(注意滚动条的 width
在这种情况下固定为 20px
并且没有任何动态代码)。
此解决方案允许滚动整个文档,同时保持使用鼠标滚动每个嵌套 div 的可能性。希望我理解正确。
这只是一个概念,它不会阻止嵌套元素随window一起滚动。但是可以改进。
Array.prototype.slice.call( document.getElementsByClassName('sbRemover') )
.forEach(function (div) {
var scroll = 0,
mousedown = false,
mouseBtnHandler = function (e) {
mousedown = e.type == 'mousedown';
}
div.addEventListener('scroll', function (e) {
// Change of div's scrollTop. Negative when scrolling down
var diff = scroll - e.target.scrollTop;
// Save new scroll value to be able to compare with it later
scroll = e.target.scrollTop;
// Do nothing when div is scrolled by dragging the scrollbar
if (!mousedown) {
// Scroll the window to the same amount of pixels the div was scrolled
window.scrollTo(window.pageXOffset, window.pageYOffset - diff);
}
});
div.addEventListener('mouseup', mouseBtnHandler);
div.addEventListener('mousedown', mouseBtnHandler);
});
body, div {
margin: 0;
padding: 0;
}
.block{
position: relative;
width:100vw;
height:100vh;
overflow: hidden;
z-index: 1;
opacity: 100;
}
.sbRemover{
width:100%;
height:100%;
padding-right:15px;
overflow: auto;
}
.largeContent{
height:225vh;
}
.smallContent{
height:100vh;
}
<div id="simpleCanvas">
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div id="ok" class="largeContent" style="background-image: url('http://silviahartmann.com/background-tile-art/images/grey-repeating-background-8.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://a1star.com/images/star--background-seamless-repeating9.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://people.stfx.ca/x2011/x2011ane/info102/assignment1/11500341-abstract-colorful-repeating-background.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
</div>