Почему Chrome для мобильных устройств не перерисовывает мой фиксированный заголовок?

У меня есть заголовок, который я хотел бы контролировать видимость при прокрутке. При прокрутке вниз страницы заголовок должен работать как любой элемент. При прокрутке страницы вверх, независимо от положения страницы, я хотел бы показать заголовок при подъеме страницы. Это поведение может быть лучше всего понято на простом примере.

Я слушаю события прокрутки и обновляю фиксированную позицию div с отрицательным верхним значением:

$(function()
{
    var $header = $("#header");
    var $window = $(window);

    var headerHeight = $header.outerHeight();
    var headerY = $header.outerHeight();
    var scrollY = $window.scrollTop();

    $window.on("scroll", function()
    {
        headerY += scrollY - $window.scrollTop();
        if (headerY > headerHeight)
        {
            headerY = headerHeight;
        }
        else if (headerY < 0)
        {
            headerY = 0;
        }
        $header.css(
            {
                top: headerY - headerHeight,
            });
        scrollY = $window.scrollTop();
    });
});

Тем не менее, поведение в Chrome для мобильных устройств совсем не то, что я ожидал. Заголовок часто не анимируется и мгновенно появляется или исчезает при достижении границ. Когда это действительно оживляет, производительность прерывисто нерегулярна и часто рисует только один - три кадра. Такое поведение не проявляется при использовании мобильной эмуляции рабочего стола Chrome; это происходит только на реальном устройстве.

Кажется, что это происходит только при работе с элементом фиксированной позиции в верхней части страницы. Если я пытаюсь изменить фиксированный элемент другим способом, например, перемещая его сбоку или снизу, все работает намного ближе к ожидаемому. Фактически, если я изменю как верхний элемент с фиксированной позицией, так и боковой элемент с фиксированной позицией, верхний элемент будет вести себя более равномерно, как это происходит.

Почему Chrome для мобильных устройств так нестабилен с элементами фиксированного положения вверху страницы? Есть ли способ, которым я могу объяснить это в сжатой форме?

2 ответа

Решение

Попробуйте использовать некоторые аппаратно ускоренные преобразования CSS3. Вместо того, чтобы использовать top чтобы позиционировать свой элемент, попробуйте использовать transform:translateY,

Также попробуйте добавить transform:translateZ(0) на элементе заголовка.

Здесь много в игре. Мобильные устройства не такие мощные, как настольные компьютеры, и анимация иногда может показаться вялой. Особенно, когда на странице присутствуют тени CSS.

Я не уверен, что вызывает это, но я бы дал шанс window.requestAnimationFrame функция всегда поддерживается (вам нужно проверить поддержку старых браузеров, таких как IE9).

Идея состоит в том, чтобы перерисовывать экран всякий раз, когда мобильный графический процессор готов перерисовать (обычно каждые 16,6 мс), а не заполнять его запросом, который не может быть обработан своевременно.

Поэтому я бы попробовал что-то вроде этого (не проверено):

$(function()
{
    var $header = $("#header");
    var $window = $(window);

    var headerHeight = $header.outerHeight();
    var headerY = $header.outerHeight();
    var scrollY = $window.scrollTop();
    var requestId;

    $window.on("scroll", function()
    {
        //run only when no request is pending.
        if (requestId === undefined) {
             requestId = window.requestAnimationFrame(animateHeader);
        }
    });

    function animateHeader() {
        requestId = undefined;

        headerY += scrollY - $window.scrollTop();
        if (headerY > headerHeight)
        {
            headerY = headerHeight;
        }
        else if (headerY < 0)
        {
            headerY = 0;
        }
        $header.css(
            {
                top: headerY - headerHeight,
            });
        scrollY = $window.scrollTop();
    }

});

Поскольку я не уверен, что это что-то решает, некоторые отзывы, как только вы попробовали, были бы хорошими!

  • Отредактированное условие requestAnimationFrame должно быть вызвано.
Другие вопросы по тегам