JavaScript window.scroll延迟导致异步重绘

alt*_*alt 5 javascript safari performance scroll webkit

目标

所以我<div>在单列布局中有一个列表,其中包含"活动"或"非活动"类.活动类在项目右侧显示图形,而非活动类不显示.我进行了设置,以便按下向上或向下箭头键将"活动"类(以​​及带有它的图形)移动到上一个或下一个项目.它不是动画,但您可以直观地看到图形消失并重新出现在上方或下方的标签上.

现在我想让页面向下滚动箭头按键,这样项目的上边缘总是在同一个位置.由于元素列表大于页面窗口,因此必须自动滚动浏览器,以便所选<div>内容始终位于屏幕的中心...

代码

//Paging through items with arrow keys
theWindow.keydown(function (e) {
    var key = e.keyCode,
        oldItem = $('li.active')

    if ((key === 40 && oldItem.next().length) || (key === 38 && oldItem.prev().length)) {
        var theWindowMod = (window.innerHeight / 2) + 43,
            theHTML = $('html'),
            theDetail = $('.detail')

        theHTML.addClass('notransition')

        if (key === 40 && oldItem.next().length) {
            oldItem.removeClass('active').next().addClass('active')
        } else if (key === 38 && oldItem.prev().length) {
            oldItem.removeClass('active').prev().addClass('active')
        }

        var newItem = $('li.active')

        window.scroll(0, newItem.offset().top - theWindowMod)
        e.preventDefault()
        $('.detail-inner.active').fadeOut(0).removeClass('active')
        $('section.active, .tab.active').removeClass('active')
        newItem.find('.tab').add(theDetail).addClass('active')
        theDetail.find('.detail-' + newItem.attr('class').split(' ')[0]).addClass('active').fadeIn(0)

        setTimeout(function () {
            theHTML.removeClass('notransition')
        }, 1)
    }
});
Run Code Online (Sandbox Code Playgroud)

问题

问题是在所有版本的Safari中,但没有其他浏览器,window.scroll方法仅略微落后于CSS类切换性能.发生的事情是它们最终出现在两个不同的重绘事件中,当您向下滚动时,页面看起来像是"故障",因为您可以在浏览器向下滚动之前简单地看到下一个元素右侧的图形.

现场演示

你可以在这里观看:

http://hashtag.ly/#minecraft

使用箭头键翻阅项目.注意跳跃.我该如何解决这个问题?

tif*_*fon 1

我认为避免该问题的解决方案是您最好的选择。

从用户体验的角度来看,当我浏览网站时,我不喜欢网站篡夺滚动位置的控制权。

另外,对于拥有较高浏览器的人(例如我),目前在详细信息和所选帖子之间可能存在大量白色空间。(见截图)

详细信息与选定的帖子相去甚远。

我的建议是更改设计,以便详细信息显示在所选帖子旁边,并让用户进行滚动。使用 CSS 控制细节的位置,使它们位于所选帖子的旁边,将其与其他所有内容放在相同的渲染周期中。

更接近所选帖子的详细信息可能如下所示:

详细信息更接近所选帖子。

更新:

想想看,AOL 的电子邮件客户端 Alto 具有您已经实现的用户体验。在 Alto 中,如果您使用按键浏览,左栏会自动滚动。但是,您实际上并没有滚动,而是将内容添加到容器元素中并将其带入视图(我忘记这叫什么......虚拟化?)。看起来他们正在管理所有与滚动相关的视觉效果和行为,并且没有使用本机功能。所以,这都是 JS 控制的 CSS 和 DOM 操作,实际上没有调用scrollTo()。这将所有这些都放在同一个渲染周期中。

美国在线阿尔托电子邮件