jQuery .проблема с синхронизацией delay(), не все анимации имеют постоянную задержку?

#jquery #animation #delay #timing

#jquery #Анимация #задержка #синхронизация

Вопрос:

У меня есть простой фрагмент кода jQuery, который скрывает группу объектов галереи при нажатии на элементы управления, а затем показывает отфильтрованные объекты один за другим.

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

Вот код:

 $(document).ready(function() {

    var controls = $('#portfolio-nav'); 
    var gallery = $('#gallery');

    $('a', controls).click(function(){

        /* setup variables */
        var nav             = $(this).closest('ul');
        var listItem        = $(this).parent();
        var current         = 'current';
        var classes         = listItem.attr("class").split(/s/);
        var elementsToShow  = new Array();
        var allElements     = gallery.children();

        /* filter classes to excude .current */
        classes = jQuery.grep(classes, function(value){
            return value != current;
        });
        var sector = classes[classes.length -1];

        /* remove all .current classes */
        nav.children('.current').each(function() {    
            $(this).removeClass('current');
        });

        /* add the .current class to the clicked li */
        $(this).parent().addClass('current');

        /* define which elements to show */
        $(allElements).each(function() {

            var element = $(this);          
            var elementSectors = element.attr("class").split(/s/);

            if(sector !== 'all'){

                if(jQuery.inArray(sector, elementSectors) !== -1){
                    elementsToShow.push(element);
                }

            } else {
                elementsToShow.push(element);
            }

        });

        /* log the elements */
        //console.log(elementsToShow);

        /* hide/show all the elements */
        animateThem(allElements, elementsToShow);

        /* clear the array for the next click */
        elementsToShow.length = 0;

        return false;
    });

    function animateThem(allElements, elementsToShow){

        $(allElements).fadeOut('fast').delay(200);

        $(elementsToShow).each(function(index) {
            $(this).delay(100*index).fadeIn('normal');
        });

    }

});
  

Вот краткий фрагмент html:

 <nav id="portfolio-nav">
    <ul>
        <li class="all current"><a href="#all">All</a></li>
        <li class="branding"><a href="#branding">Branding</a></li>
    </ul>
</nav>

<div id="gallery">
    <div class="grid-3 media-holder branding">
        ...
    </div>
    <div class="grid-3 media-holder marketing">
        ...
    </div>
</div>
  

Вероятно, это легко исправить, поскольку мой jQuery не очень хорош, но если кто-нибудь знает причину, по которой это произойдет, я хотел бы знать.

Приветствия,

Дэйв

Редактировать: Возникли проблемы с объявлением элементов массива и получал необъявленную ошибку … после некоторой настройки его работы, как ожидалось (благодаря Дэнни Хансену), JSFiddle ниже, если кому-то интересно:

http://jsfiddle.net/daveaspinall/8VKad/9/

Комментарии:

1. В общем, я бы предпочел использовать метод обратного вызова вместо расчетной задержки.

Ответ №1:

Не совсем уверен, может быть какая-то проблема с синхронизацией.

Почему бы вам не попробовать использовать интервал:

 var intCount = 0;
var interval = setInterval(function () {
    if(typeof elementsToShow[intCount] != undefined) {
         if(elementsToShow[intCount] != "fired") {
              elementsToShow[intCount].fadeIn('normal');
              elementsToShow[intCount] = "fired";
              intCount  ;
         }
    } else {
    //End of array, clear the interval
         clearInterval(interval);
    }
}, 100);
  

Вот как это можно было бы сделать, используя интервал для определения времени событий. Попробуйте и сообщите, сработало ли это 🙂

Edit1 Отредактирован, чтобы исправить ошибку. — (Благодаря Brighty)

Edit2 Исправлена функция fadeIn. Попробуйте сейчас.

Комментарии:

1. привет, Дэнни, спасибо за быстрый ответ! Я получаю сообщение об ошибке «elementsToShow[intCount] не определено»? Есть идеи?

2. Убедитесь, что вы заменили текущий $.each на новый метод интервала. Насколько я вижу, ваш массив с элементами поставляется с параметрами функции. Это означает, что если вы используете это вне функции, это приведет к неопределенным ошибкам. Попробуйте записать в консоль elementsToShow и убедитесь, что он проиндексирован 0-999, также убедитесь, что строка «if (typeof elementsToShow[intCount] !== undefined) {» работает правильно, если нет, попробуйте использовать следующее: «if (elementsToShow[intCount] != undefined) {»

3. да, я заменил старую функцию .each () на указанную выше внутри функции. Я продолжу смотреть, не является ли это чем-то очевидным (обычно так и есть)

4. У вас должна быть неопределенная часть без кавычек. Иначе это не сработает. Причина этого в том, что мы считаем наш путь вверх по массиву, и когда он достигает неопределенного индекса (что означает, что массив завершен), он завершает интервал. Но попробуйте другой пример неопределенной проверки и посмотрите, работает ли он. Еще одна вещь, которую вы могли бы сделать, если это отнимает слишком много вашего времени, — это удалить метод задержки из вашего $.each и вместо ‘normal’ в качестве времени вы могли бы просто продлить время, необходимое для его затухания. Так что у него все еще есть этот вид события trail 🙂

5. Было внесено несколько исправлений. Попробуйте новый пример 🙂