Анимация блоков jquery - перемещение с эффектом всплывающих элементов

Анимация блоков jquery - перемещение с эффектом всплывающих элементов

Существует немало примеров анимации блоков на jQuery с эффектами перемещения, появления, сдвига, скрытия и так далее. Однако, многие из них демонстрируют лишь небольшие отдельные эффекты из-за чего может создаться неправильное впечатление о возможностях jQuery. Ведь, мало где встречаются примеры того, как из простых элементов можно легко создать красивую и сложную анимацию. А даже если и встречается, то обычно такая анимация уже зашита и оформлена в виде плагина, в структуре которого еще необходимо разбираться. В данной же статье будет показано, что сделать красивую и сложную анимацию своими руками очень просто.

 

Идея сложной анимации на jquery с эффектами перемещения всплывающих блоков

В качестве заготовки, возьмем проект из одной из предыдущих статей про валидацию форм на jQuery. Казалось бы, прокрутки и подсветки после валидации полей может быть вполне достаточно для помощи пользователям, при заполнении больших и сложных форм. Однако, в примере все же есть недостатки. Так, например, если блоков много и ошибки находятся в нескольких блоках, то даже если пользователь будет проходится по всем блокам и исправлять их, существует вероятность, что не помеченные блоки где-то в середине формы будут не исправлены и пользователю снова придется прокручивать страницу вверх, а затем и вниз, и исправлять ошибки.

Тут и возникает идея, а что если пользователю последовательно показать все блоки с ошибками, а так же расположить эти блоки в самом концу формы. После чего, снова направить пользователя к первому блоку с ошибкой. В таком случае, пользователь будет точно знать, что во всех блоках, начиная с самого верхнего, есть ошибки, которые необходимо исправить. Схематично идея выглядит следующим образом:

Идея сложной анимации на jquery с перемещением всплывающих блоков

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

Если вы думаете, что сделать такую анимацию очень сложно, то вы ошибаетесь. У автора на это ушло не более 10-15 минут. И вот как это можно сделать.

Примечание: Конечно, для быстрого составления такой анимации потребуется опыт. Однако, если вы сразу будете себя приучать к сложным задачам, то в будущем составление подобного рода анимации покажется вам далеко не сложной задачей.

 

Реализуем валидацию на jQuery с эффектом перемещения всплывающих блоков

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

Прежде всего, для наглядности упростим формы валидации и дополним их заголовками, чтобы было видно все шаги анимации. Другими словами, заменим html-код блоков на следующий:

<div class="form-2 form">
    <div class="header">Валидация формы с прокруткой</div>
    <div class="form-block">
        <div class="header">Блок 1 с ошибкой</div>
        <div class="label">Имя</div>
        <div class="field"><input type="text" name="UserName" class="field-input required alphanumeric" /></div>
        <div class="label">Email</div>
        <div class="field"><input type="text" name="Email" class="field-input required email" /></div>
        <div class="label">URL</div>
        <div class="field"><input type="text" name="Url" class="field-input url" /></div>
        <div class="label">Дата форматы ГГГГ-ММ-ДД и ДД.ММ.ГГГГ</div>
        <div class="field"><input type="text" name="Date" class="field-input date" /></div>
    </div>
    <div class="form-block">
        <div class="header">Блок 2 без ошибки</div>
        <div class="label">Имя</div>
        <div class="field"><input type="text" name="UserName" class="field-input alphanumeric" /></div>
        <div class="label">Email</div>
        <div class="field"><input type="text" name="Email" class="field-input email" /></div>
        <div class="label">URL</div>
        <div class="field"><input type="text" name="Url" class="field-input url" /></div>
        <div class="label">Дата форматы ГГГГ-ММ-ДД и ДД.ММ.ГГГГ</div>
        <div class="field"><input type="text" name="Date" class="field-input date" /></div>
    </div>
    <div class="form-block">
        <div class="header">Блок 3 с ошибкой</div>
        <div class="label">Имя</div>
        <div class="field"><input type="text" name="UserName" class="field-input required alphanumeric" /></div>
        <div class="label">Email</div>
        <div class="field"><input type="text" name="Email" class="field-input required email" /></div>
        <div class="label">URL</div>
        <div class="field"><input type="text" name="Url" class="field-input url" /></div>
        <div class="label">Дата форматы ГГГГ-ММ-ДД и ДД.ММ.ГГГГ</div>
        <div class="field"><input type="text" name="Date" class="field-input date" /></div>
    </div>
    <div class="form-block">
        <div class="header">Блок 4 без ошибки</div>
        <div class="label">Имя</div>
        <div class="field"><input type="text" name="UserName" class="field-input alphanumeric" /></div>
        <div class="label">Email</div>
        <div class="field"><input type="text" name="Email" class="field-input email" /></div>
        <div class="label">URL</div>
        <div class="field"><input type="text" name="Url" class="field-input url" /></div>
        <div class="label">Дата форматы ГГГГ-ММ-ДД и ДД.ММ.ГГГГ</div>
        <div class="field"><input type="text" name="Date" class="field-input date" /></div>
    </div>
    <div class="form-block">
        <div class="header">Блок 5 с ошибкой</div>
        <div class="label">Имя</div>
        <div class="field"><input type="text" name="UserName" class="field-input required alphanumeric" /></div>
        <div class="label">Email</div>
        <div class="field"><input type="text" name="Email" class="field-input required email" /></div>
        <div class="label">URL</div>
        <div class="field"><input type="text" name="Url" class="field-input url" /></div>
        <div class="label">Дата форматы ГГГГ-ММ-ДД и ДД.ММ.ГГГГ</div>
        <div class="field"><input type="text" name="Date" class="field-input date" /></div>
    </div>
    
    <div class="clear"></div>
    <div class="btn-panel">
        <button class="save-button" >Отправить форму </button>
    </div>
</div>

А теперь, необходимо изменить код скрипта следующим образом:

function animateBlocks(blocks, index, onComplete) {
 
    if(!blocks) {
        if (typeof (onComplete) === 'function') onComplete();
        return;
    }
    if (blocks instanceof jQuery && blocks.length < index + 1) {
        if (typeof (onComplete) === 'function') onComplete();
        return;
    }
 
    var item = $(blocks[index]);
 
    $.scrollTo(item, 700, { 
        // Задаем смещение вверх, 
        // чтобы граница блока не оказалась в самом верху окна браузера
        offset: { 
            top: -20 
        }, 
        // Как только перемещение закончено, запускаем анимацию подкраски
        onAfter:function () {
            // Подкрашиваем блок на полсекунду и снова убираем цвет
            item.animate({ backgroundColor: 'rgb(240, 131, 131)' }, 500, "linear", function () {
                item.animate({  backgroundColor: 'white'  }, 500, "linear", function () {
                    // Скрываем подкрашенный блок
                    item.animate({ opacity: 0, height: 0  }, 500, 'linear', function () {
                        // передвигаемся к последнему блоку
                        $.scrollTo($('.form-2 .form-block:last'), 700, function () {
                            // Отображаем блок 
                            item.insertAfter($('.form-2 .form-block:last')).animate({ opacity: 1, height: '100%' }, 500, 'linear', function () {
                                // Пододвигаемся к блоку
                                $.scrollTo(item, 700, { 
                                    // Задаем смещение вверх, 
                                    // чтобы граница блока не оказалась в самом верху окна браузера
                                    offset: { 
                                        top: -20 
                                    }, 
                                    // Как только перемещение закончено, запускаем анимацию подкраски
                                    onAfter:function () {
                                        // Снова подкрашиваем блок
                                        item.animate({ backgroundColor: 'rgb(240, 131, 131)' }, 500, "linear", function () {
                                            item.animate({  backgroundColor: 'white'  }, 500, "linear", function () {
                                                // Запускаем следующий блок
                                                animateBlocks(blocks, index + 1, onComplete);
                                            });
                                        });
                                    }
                                });
                            });
                        });
                        
                    });
                });
            });
        }
    });
}
 
$(function () {
    // Ручная валидация, доступная в любой момент
    $('.form-2 .save-button').on('click', function () {
        if(window.validation.isValid({ container: '.form-2' })) {
            alert('Валидация второй формы прошла успешно!');
        }
        // Если в форме есть ошибки, то запускаем анимацию
        else {
            // Находим блок с ошибкой
            var errorBlocks = $('.form-2').find('.input-error').parent().parent(),
                item = $(errorBlocks[0]);
 
            animateBlocks(errorBlocks, 0, function () {
                // Передвигаемся к самому первому блоку с ошибкой
                $.scrollTo(item, 700, { 
                    // Задаем смещение вверх, 
                    // чтобы граница блока не оказалась в самом верху окна браузера
                    offset: { 
                        top: -20 
                    }, 
                    // Как только перемещение закончено, запускаем анимацию подкраски
                    onAfter:function () {
                        // Подкрашиваем блок на полсекунду и снова убираем цвет
                        item.animate({ backgroundColor: 'rgb(240, 131, 131)' }, 500, "linear", function () {
                            item.animate({  backgroundColor: 'white'  }, 500, "linear", function () {
                            });
                        });
                    }
                });
            });
        }
    });
    
});

Код может показаться вам сложным. Однако он очень прост. Во-первых, создается рекурсивная функция "animateBlocks", которая выполняет для каждого блока последовательную анимацию, а затем запускает себя же для следующего элемента. Во-вторых, вся кажущаяся сложность заключается только в том, что вызов каждого следующего эффекта анимации выполняется в функции обработчике конца анимации. Если посмотреть на код, то это легко заменить по сдвигам. Тем не менее, приведем последовательное выполнение анимации для одного блока:

  1. Прокручиваем экран до блока с ошибкой - функция scrollTo
  2. Подсвечиваем блок с ошибкой - animate с параметром backgroundColor
  3. Скрываем блок с ошибкой - animate c параметрами opacity и height
  4. Прокручиваем экран до последнего блока в форме - снова функция scrollTo
  5. Переносим блок в нижнюю часть - обычная вставка insertAfter (помните, что блок с ошибкой еще невидим)
  6. Для нижнего блока с ошибкой запускаем анимацию появления - animate c параметрами opacity и height
  7. Снова прокручиваем до нижнего блока на случай если край формы находится в самом низу страницы - функция scrollTo
  8. Подкрашиваем блок с ошибкой, чтобы обратить внимание пользователя на то, где появился блок - animate с параметром backgroundColor
  9. Переходим к следующему блоку - рекурсивный вызов animateBlocks. 
  10. Если же блок был последний, с точки зрения анимации, то снова прокручиваем экран до первого блока с ошибкой и подкрашиваем его (помните, что теперь все блоки с ошибкам находятся в самом низу)

Как видите, вся сложность такой анимации в основном заключается только в том, чтобы выстроить необходимый порядок вызова, а так же в том, чтобы правильно указать параметры, расставить скобочки и закрывающие символы. Реальной какой-то сложности тут нет. И вот пример того, как был перенесен один из блоков:

Пример переноса блока при валидации 

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

Теперь, вы знаете, что сложную и красивую анимацию часто можно сделать из простых эффектов без каких-либо особых сложностей.

Ссылка для скачивания готового проекта находится тут:

validate-high-animate.zip

☕ Понравился обзор? Поделитесь с друзьями!

Добавить комментарий / отзыв

Комментарий - это вежливое и наполненное смыслом сообщение (правила).



* Нажимая на кнопку "Отправить", Вы соглашаетесь с политикой конфиденциальности.
Присоединяйтесь
 

 

Программы (Freeware, OpenSource...)