Кросс-браузерная производительность JQuery: .animate () для .hover () на более чем 100 DOM - PullRequest
3 голосов
/ 07 марта 2012

Это мое затруднение.

Позвольте мне установить сцену:

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

<div id="container">
    <!-- The container's width is 95% of the window -->
    <img alt="" src="images/aspect-holder.png">
    <!-- This image makes sure the container retains the correct aspect ratio* -->
    <a href="link1" class="element col1 row1">
        <span>Some</span>
        <span>Text</span>
              ...
    </a>
    <a href="link2" class="element col1 row2">
        <span>Other</span>
        <span>Text</span>
              ...
    </a>
    <a href="link3" class="element col1 row3">
        <!-- as above -->
    </a>
              ...
              ...
    <a href="link100something" class="element col18 row9">
        <!-- as above -->
    </a>
</div>

* Техника с использованием изображения для сохранения соотношения сторон объясняется здесь

CSS для сетки довольно прост, и единственное, на что следует обратить внимание, это то, что я устанавливаю размер шрифта для интервалов в теге привязки в процентах, чтобы я мог использовать JQuery для простого манипулирования ими, манипулируя шрифтом. размер их родителя (якоря) или родителя их родителя (#container).

Теперь о проблеме:

Что я хотел, кроме динамического характера сетки, так это то, что всякий раз, когда пользователь наводит курсор на одну из них, он должен «увеличивать масштаб». По сути, при вводе мышью окно будет увеличиваться по высоте и ширине и уменьшать его верхний и левый поля, чтобы «выскочить» из страницы. Ниже приводится JQuery, который я написал, чтобы собрать все воедино: (извиняюсь за любые вопиющие ошибки, я здесь, чтобы учиться)

container = $('#container');
anchor = container.find('a');
//The Globals have more unique names but I wrote them like this here
//to make it easier to read

//This part handles the font-size resize on Load and on Resize
function fontfix() {
    container.css('font-size', anchor.width() + 'px');
}

$(function() {
    fontfix();
});

$(window).resize(function() {
    fontfix();
});

//This is the code that handles the 'smooth' hover* animation
anchor.hover(function() {
    $(this).filter(':not(:animated)').css('z-index', 2).animate({
        marginTop: '-1.9%',
        marginLeft: '-1.5%',
        height: '15%',
        width: '8%',
        fontSize: '157%'
    });
}, function() {
    $(this).css('z-index', 1).animate({
        marginTop: '0%',
        marginLeft: '0%',
        height: '9.5393%',
        width: '5.2604%',
        fontSize: '100%'
    }, function() {
        $(this).attr('style', '');
    });
});

* .filter (': not (: animated)') основан на статье о полной анимации Jquery Криса Койера из CSS-Tricks.

И это работает! ... Ну, в WebKit и Opera, или в других браузерах для менее чем 30 или 40 элементов. С более чем 100 элементами на Firefox 10 он запинается и несколько отстает, а на IE8 - практически слайд-шоу. Это разочаровало меня без конца, так как я надеялся сделать его максимально кроссбраузерным, и поэтому я очень надеюсь, что вы, девочки и парни, сможете помочь.

Итак, подведем итоги

  1. Я обманул глобалов? Должен ли я использовать что-то другое?
  2. Есть ли способ заставить анимацию работать плавно во всех браузерах?
  3. Есть ли какие-либо другие изменения в этом коде, которые вы бы сделали? Или еще что-нибудь отметить?

Спасибо, что прочитали это далеко, и извините за длинный пост! Любая помощь с этим приветствуется.

Демонстрация на JsFiddle

Ссылка на скрипку: http://jsfiddle.net/kkubD/
На Chrome это работает как сон, на FF вы должны увидеть заикание, а на IE - еще более заикание.

Кроме того, я понимаю, что мог бы и, возможно, должен использовать неупорядоченный список и, таким образом, обернуть все свои якоря в <li> с, но я не смог найти достаточно убедительной причины для этого, поскольку сетка в ее текущем формате выглядит удовлетворительно (даже лучше) даже без включенного CSS. Я думаю, что я нашел бы улучшенную возможность сканирования или производительность достаточно веской причиной, но не знаю, что это что-то добавит. Я вообще не прав в этом?

1 Ответ

2 голосов
/ 08 марта 2012

Макс

У меня была старая добрая пьеса с этим, и я придумал что-то лучше Opera, которая изначально была такой же, как вы описываете для FF.

Результатом является двухэтапная пользовательская анимация с мгновенным первым шагом, затем setTimeout() для задержки перед вторым шагом. Каждый шаг использует .css(...), чтобы вызвать одну из трех жестко закодированных карт.

Обработка

mouseenter и mouseleave делегирована контейнеру, и, хотя это не кажется особенно важным для производительности (на моем оборудовании), она должна потреблять меньше памяти.

В целом, я считаю, что результирующая производительность варьируется в зависимости от капризов того, насколько большой временный интервал ОС (Win 7 здесь) решает дать моей вкладке Opera. В худшем случае визуальный эффект все еще немного вялый и в лучшем случае очень плавный. Это варьируется от минуты к минуте и от обновления к обновлению.

Вот код:

$(function() {
    var iam_container = $('#container');
    var iam_anchor = iam_container.find('a').data('t', null);

     $(window).resize(function() {
        iam_container.css('font-size', iam_anchor.width() + 'px');
    }).resize();

    var css_0 = {
        marginTop: 0,
        marginLeft: 0,
        height: '9.5393%',
        width: '5.2604%',
        fontSize: '100%',
        zIndex: 0
    };
    var css_1 = {
        marginTop: '-0.95%',
        marginLeft: '-0.75%',
        height: '12.27%',
        width: '6.63%',
        fontSize: '125%',
        zIndex: 1
    };
    var css_2 = {
        marginTop: '-1.9%',
        marginLeft: '-1.5%',
        height: '15%',
        width: '8%',
        fontSize: '157%',
        zIndex: 2
    };

    function anim($elem, map, delay) {
        clearTimeout($elem.data('t') || null);
         $elem.css(css_1).data('t', setTimeout(function(){$elem.css(map);}, delay));
    }

    iam_container.on('mouseenter', 'a', function() {
        anim($(this), css_2, 50);
    }).on('mouseleave', 'a', function() {
        anim($(this), css_0, 50);
    });
});

Задержка 50 мс является экспериментальной и может быть лучше при 100 мс или 150 мс, в противном случае промежуточный шаг анимации может не восприниматься на более быстром оборудовании.

А вот и скрипка :

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...