首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Android上修复动作锁定为滚动的Jank

在Android上修复动作锁定为滚动的Jank
EN

Stack Overflow用户
提问于 2013-09-23 16:25:34
回答 1查看 1K关注 0票数 0

我正在创建一个类似于地址栏的标题。其效果是,标题是一个伪粘性标题,当您向下滚动时滚动出视图,然后开始向上滚动标题,滚动回视图。

现在,它在桌面上运行得很好(大约60 for ),但在( Nexus 7,2013)上却充满了jank。

演示: jsFiddle

头部和内容区域都使用transform translateY移动,它们比pos:top更具性能。

我还使用requestAnimationFrame来取消滚动,并且只在浏览器最方便的时候更改属性。

标头是position: fixed; top: 0;,然后在transform: translateY(...);中滚动,然后从视图中滚动。另外,我使用的是transform: translateY(...);,而不是使用边距顶从标题下面获取内容。

我的js的基本结构如下:

代码语言:javascript
复制
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正在处理,而不应该进行绘制。

编辑:在与亚行进行调试时,似乎在每个帧中都有一堆清晰的灰色勾画时间。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-24 21:29:20

事实证明,即使我使用的是transform: translateY(),您仍然需要添加translateZ(0)来查看层的好处,并加快它的速度。

但是,我也更新了我的代码以使用对象字面代码样式,并通过读取然后写入消除了时间线中的forced synchronous layout警告。这与requestAnimationFrame耦合在一起。

演示: jsFiddle

代码语言:javascript
复制
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)添加到元素中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18964267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档