我有一个网页,其中有三个div同步在一起。
+----------+
| TOP |
+---+----------+
| | ||
| L | CENTER ||
| |_________||
+---+----------+
<!--Rough HTML-->
<div>
<div class="topbar-wrapper">
<div class="topbar"></div>
</div>
<div class="container">
<div class="sidebar-wrapper">
<div class="sidebar"></div>
</div>
<div class="center-wrapper"> <!-- Set to the window size & overflow:scroll -->
<div class="center"></div> <!-- Has the content -->
</div>
</div>
</div>
中心div有滚动条,水平和垂直。顶部和左侧div没有滚动条。相反,当移动水平滚动条时,滚动事件会相应地更新顶部div margin-left
。同样,当移动垂直滚动条时,margin-top
会更新。在这两种情况下,它们都设置为负值。
$('.center-wrapper').scroll(function(e) {
$('.sidebar').css({marginTop: -1 * $(this).scrollTop()});
$('.topbar').css({marginLeft: -1 * $(this).scrollLeft()});
});
这在Chrome和Firefox中运行良好。但在Safari中,移动滚动条与正确设置的负边距之间存在延迟。
有更好的方法吗?或者有没有办法摆脱Safari的滞后?
编辑:
查看这个小提琴,看看Safari中的滞后:http://jsfiddle.net/qh2K3/
答案 0 :(得分:12)
如果this JSFiddle效果更好,请告诉我。我也经历了同样的“滞后”(OS X上的Safari 7)和这些小的CSS更改显着改进了它。我最好的猜测是,Safari很懒,并没有开启其高性能电机。我们可以使用一些简单的CSS强制Safari启用它:
.topbar-wrapper, .sidebar-wrapper, .center-wrapper {
-webkit-transform: translateZ(0);
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
}
通过将部分工作卸载到GPU,可以在Safari中启用hardware accelerated CSS。它改进了浏览器中的渲染,这可能是延迟中的问题。
答案 1 :(得分:3)
我已经有过几次这个问题了,当基于这样的事件逐步移动元素时,safari似乎滞后了。
以下是我过去解决问题的方法。
在支持硬件加速的浏览器中,使用任何“3d”CSS属性将启用硬件acc。
如果支持3D变换,我们也可以使用translate3d来移动元素,因为这样可以比移动像素更平滑。
这意味着我们首先必须找出CSS转换属性的正确前缀,然后检查对3D转换的支持。如果我们有支持,翻译元素,如果不是移位像素。
通过计算没有库的前缀和3D支持,它应该尽可能快,并且没有依赖性。
var parent = document.querySelector('.center-wrapper'),
sidebar = document.querySelector('.sidebar'),
topbar = document.querySelector('.topbar'),
has3D = false,
transform = null,
transforms = {
'webkitTransform' : '-webkit-transform',
'OTransform' : '-o-transform',
'msTransform' : '-ms-transform',
'MozTransform' : '-moz-transform',
'transform' : 'transform'
};
for (var k in transforms) if (k in parent.style) transform = k;
if ( transform !== null ) {
sidebar.style[transform] = 'translate3d(0,0,0)'; // start hardware acc
topbar.style[transform] = 'translate3d(0,0,0)'; // start hardware acc
// check support
var s = window.getComputedStyle(sidebar).getPropertyValue(transforms[transform]);
has3D = s !== undefined && s.length > 0 && s !== "none";
}
if (has3D) {
parent.onscroll = function (e) {
sidebar.style[transform] = 'translate3d(0px, '+ (this.scrollTop * -1) +'px, 0px)';
topbar.style[transform] = 'translate3d('+ (this.scrollLeft * -1) +'px, 0px, 0px)';
}
}else{
parent.onscroll = function (e) {
sidebar.style.marginTop = (this.scrollTop * -1) + 'px';
topbar.style.marginLeft = (this.scrollLeft * -1) + 'px';
}
}
请记住将它放在DOM中的元素之后,如</body>
之前,或者如果不可能,则必须将其包装在DOM就绪处理程序中。
作为旁注,IE7及以下版本不支持querySelector,如果这是一个问题,你必须将其填充。
答案 2 :(得分:2)
更改:
$('.center-wrapper').scroll(function(e) {
$('.sidebar').css({marginTop: -1 * $(this).scrollTop()});
$('.topbar').css({marginLeft: -1 * $(this).scrollLeft()});
});
收件人:
var _scroller = $('.center-wrapper'),
_swrapper = $('.sidebar-wrapper'),
_twrapper = $('.topbar-wrapper');
_scroller.scroll(function (e) {
_swrapper.scrollTop(_scroller.scrollTop());
_twrapper.scrollLeft(_scroller.scrollLeft());
});
如果必须每次都重新创建jquery对象.scroll()
, $(this)
将会非常努力。
昨晚在评论中写了这篇文章,虽然还没有测试,但今天实际上觉得应该添加这与性能直接相关。
我们可以尝试一下 - here
还有另外一个我们可以删除的jquery方法调用。 .scrollTop()
和.scrollLeft()
通过缓存并返回原始_scrollernative = _scroller.get(0)
来使用随时可用的属性scrollLeft
。
赞:
var _scroller = $('.center-wrapper'),
_scrollernative = _scroller.get(0),
_swrapper = $('.sidebar-wrapper').get(0),
_twrapper = $('.topbar-wrapper').get(0);
_scroller.scroll(function (e) {
_swrapper.scrollTop = _scrollernative.scrollTop;
_twrapper.scrollLeft = _scrollernative.scrollLeft;
});
我们可以尝试 here
我很欣赏您的代码可能会在页面上查看多个控件,这就是您使用类并需要查找S(this)
而不是使用ID的原因。
为此,我仍然会使用上面的缓存方法,但在此之前我们需要逐个创建它们。 (在我们初始化每个实例的scroll()函数之前进行缓存)
(function() {
var _scroller = $('.center-wrapper'),
_swrapper = $('.sidebar-wrapper').get(0),
_twrapper = $('.topbar-wrapper').get(0);
function setScrollers(_thisscroller) {
_scrollernative = _thisscroller.get(0);
/* start the scroll listener per this event */
_thisscroller.scroll(function (e) {
_swrapper.scrollTop = _scrollernative.scrollTop;
_twrapper.scrollLeft = _scrollernative.scrollLeft;
});
}
_scroller.each(function() { setScrollers($(this)); });
})();
我们可以尝试 here
但正如我所看到的那样.sidebar-wrapper和.topbar-wrapper是唯一的,mabye .center-wrapper也是独一无二的。
那么如何最终使用id来为这些元素缩短所有内容。
var _scroller = document.getElementById('center-wrapper'),
_swrapper = document.getElementById('sidebar-wrapper'),
_twrapper = document.getElementById('topbar-wrapper');
_scroller.onscroll = function() {
_swrapper.scrollTop = _scroller.scrollTop;
_twrapper.scrollLeft = _scroller.scrollLeft;
};
我们可以尝试 here
答案 3 :(得分:1)
而不是使用marginTop & marginLeft
来更改.sidebar & .topbar
的余量,使用scrollTop & scrollLeft
来获取溢出的div .sidebar-wrapper & .topbar-wrapper
并查看它现在是否可以在 Safari 中使用:
$('.center-wrapper').scroll(function(e) {
$('.sidebar-wrapper').scrollTop($(this).scrollTop());
$('.topbar-wrapper').scrollLeft($(this).scrollLeft());
});