我正在创建一个类似于地址栏的标题。其效果是,标题是一个伪粘性标题,当您向下滚动时滚动出视图,然后开始向上滚动标题,滚动回视图。
现在,它在桌面上运行得很好(大约60 for ),但在( Nexus 7,2013)上却充满了jank。
演示: jsFiddle
头部和内容区域都使用transform translateY移动,它们比pos:top更具性能。
我还使用requestAnimationFrame来取消滚动,并且只在浏览器最方便的时候更改属性。
标头是position: fixed; top: 0;,然后在transform: translateY(...);中滚动,然后从视图中滚动。另外,我使用的是transform: translateY(...);,而不是使用边距顶从标题下面获取内容。
我的js的基本结构如下:
var latestScrollTop = 0;
var lastReactedScrollTop = 0;
var ticking = false;
function DoScroll()
{
var builtUpScrollTop = latestScrollTop - lastReactedScrollTop;
// Fold the top bar while we are scrolling (lock it to scrolling)
$('header.main-header').css('transform', 'translateY(' ... 'px)');
HeaderHeightChange();
lastReactedScrollTop = latestScrollTop;
ticking = false;
}
function HeaderHeightChange()
{
// We need to update the margin-top for the content so we don't overlap it
$('main.content-area').css('transform', 'translateY(' ... 'px)');
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(function(){
DoScroll();
});
}
ticking = true;
}
$(window).on('scroll', function(e) {
latestScrollTop = $(window).scrollTop();
requestTick();
});效果是不完整的,因为它需要解决折叠后,你完成滚动(并被编码),但我不想复杂的问题时,只是滚动运动锁定头部是导致jank。当我上下滚动时,我会看到油漆矩形,即使我正在改变转换,我假设gpu正在处理,而不应该进行绘制。
编辑:在与亚行进行调试时,似乎在每个帧中都有一堆清晰的灰色勾画时间。

发布于 2013-09-24 21:29:20
事实证明,即使我使用的是transform: translateY(),您仍然需要添加translateZ(0)来查看层的好处,并加快它的速度。
但是,我也更新了我的代码以使用对象字面代码样式,并通过读取然后写入消除了时间线中的forced synchronous layout警告。这与requestAnimationFrame耦合在一起。
演示: jsFiddle
var myUtils = {
clamp: function(min, max, value) {
return Math.min(Math.max(value, min), max);
},
getTranslateYFromTransform: function(rawTransform) {
return parseFloat(rawTransform.match(/^matrix\((([+-]?[0-9]*\.?[0-9]*),\s*?){5}([+-]?[0-9]*\.?[0-9]*)\)$/)[3])
}
};
var scrollHeader = {
latestScrollTop: 0,
lastReactedScrollTop: 0,
headerHeight: 0,
headerTransformTranslateY: 0,
ticking: false,
requestTick: function() {
if(!scrollHeader.ticking) {
requestAnimationFrame(function(){
scrollHeader.doHeaderFold();
});
}
scrollHeader.ticking = true;
},
doHeaderFold: function() {
var header = $('header.main-header');
var builtUpScrollTop = scrollHeader.latestScrollTop - scrollHeader.lastReactedScrollTop;
scrollHeader.headerHeight = header.outerHeight();
scrollHeader.headerTransformTranslateY = myUtils.clamp(-parseInt(scrollHeader.headerHeight), 0, (myUtils.getTranslateYFromTransform(header.css('transform')) - builtUpScrollTop));
// Fold the top bar while we are scrolling (lock it to scrolling)
header.css('transform', 'translateY(' + scrollHeader.headerTransformTranslateY + 'px) translateZ(0)');
scrollHeader.headerHeightChange();
scrollHeader.lastReactedScrollTop = scrollHeader.latestScrollTop;
scrollHeader.ticking = false;
},
headerHeightChange: function() {
// We need to update the margin-top for the content so we don't overlap it
$('main.content-area').css('transform', 'translateY(' + (scrollHeader.headerHeight + scrollHeader.headerTransformTranslateY) + 'px) translateZ(0)');
}
};
$(window).on('scroll', function(e) {
//console.log(e);
scrollHeader.latestScrollTop = $(window).scrollTop();
scrollHeader.requestTick();
});这使得亚行(Nexus 7,2013)上的时间线调试看起来(非常顺利):

此外,为了摆脱第一次滚动时的小跳转,在动画前将transform: translateZ(0)添加到元素中。
https://stackoverflow.com/questions/18964267
复制相似问题