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

时间:2012-12-08 04:14:15

标签: javascript performance safari webkit scroll

目标

所以我在单列布局中有一个<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)
    }
});

问题

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

现场演示

您可以在此处观看:

http://hashtag.ly/#minecraft

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

2 个答案:

答案 0 :(得分:1)

尝试使用按钮而不是div,并在激活特定项目时使用setfocus()。浏览器将自动滚动以使聚焦按钮始终可见。您可以使用CSS使按钮看起来与div完全相同。

答案 1 :(得分:1)

我认为避免这个问题的解决方案是你最好的选择。

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

此外,对于拥有高浏览器(如我)的人来说,目前在细节和所选帖子之间可能存在大量的白色空间。 (见截图)

Details are far from selected post.

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

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

Details closer to selected post.

更新

想想看,AOL的电子邮件客户端Alto拥有您已实施的用户体验。在Alto中,如果使用键进行浏览,左列会自动滚动。但是,你实际上并没有滚动,他们将内容添加到容器元素中并将其置于视图中(我忘记了这称为虚拟化?)。看起来他们自己管理所有与滚动相关的视觉和行为,并且没有使用本机功能。所以,它是所有JS控制的CSS和DOM操作,实际上没有scrollTo()调用。这使得所有这些都处于相同的渲染周期中。

AOL Alto email