Пример создания анимированного меню

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



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

    И так, для начала нам необходимо создать статическое меню. Вот мой вариант кода:

    html
    
    <div class="bord"></div>
    <div class="head">
        <a class="headParagraph">Настройки</a>
        <a class="headParagraph">Разделы</a>
        <a class="headParagraph">Статьи</a>
        <a class="headParagraph">Галереи</a>
        <a class="headParagraph">Языки</a>
        <a class="headParagraphExit" href="#">Выход</a>
    </div>
    
    CSS
    
    .head{
    	margin: 0 auto;
    	padding: 15px 20px 3px 20px;
    	width: 90%;
    	height: 17px;
    }
    
    .bord{
    	border-top: 2px solid #000;
    	top: 35px;
    	left: 3%;
    	width: 94%;
    	position: absolute;
    }
    
    .headParagraph{
    	float: left;
    	margin-right: 40px;
    	cursor: pointer;
    	font-size: 16px;
    	color: #444;
    	margin-top: 0;
    }
    
    .headParagraphExit{
    	float: right;
    	cursor: pointer;
    	text-decoration: none;
    	color: #000;
    	font-sizq: 20px;
    }
    


    Для создания эффекта “падающей” ссылки используется класс Fx.Morph, который позволяет изменять свойства элемента в рамках CSS.

    Объявляется класс таким образом:

    var myEffect = new Fx.Morph('myElement', {duration: 'long', transition: Fx.Transitions.Sine.easeOut});


    Свойство duration может принимать значения long или short — это влияет на скорость выполнения эффекта(переход от одного значения свойства элемента к другому). Transition определяет вид анимации эффекта, подробнее со списком принимаемых значений этого свойства можно ознакомиться в официальной документации.

    Для запуска эффекта нам необходимо объявить о том, какие свойства и как будут меняться в наших объектах. Для этого существует метод start, который и запускает эффект:

    myEffect.start({
    	'height': [10, 100],
    	'width': [900, 300]
    });


    В этом примере наш элемент поменяет значение ширины и высоты — высота увеличится с 10px до 100px, а ширина уменьшится соответственно с 900px до 300px.
    Возможно так же несколько других вариантов объявлений этого метода, например:

    myEffect.start({
    	'height': 100,
    	'width': 300
    });


    или

    myEffect.start('.myClassName');


    В первом примере наш элемент поменяет свои свойства с текущих значений на те, что мы указываем в методе, а во втором случае актуальные на данный момент свойства поменяются на описанные в классе myClassName.

    Итак, для того чтобы наши ссылки “падали“ и возвращались в первоначальное положение, создадим класс, который будет менять свойства margin-top и color наших ссылок, и назовем его selected.

    .selected{
    	margin-top: 25px;
    	color: #000;
    }
    


    Теперь для того чтобы наша ссылка “падала”, необходимо применить к ней класс selected, а чтобы возвращалась в первоначальное — положение класс headParagraph.

    Для обращения к нашим элементам меню можно воспользоваться одним из двух способов, предусмотренных в mootools — это либо обращение по id элемента, либо обращение к массиву элементов по имени класса, которому принадлежит элемент, или по имени тэга обращаемся в группе однотипных элементов.
    В первом случае обращение к элементу выглядит как $(‘id_element’). Во втором случае $$(‘#tag_name.class’), $$(‘#tag_name’), $$(‘.class’) возвращает массив элементов соответствующих одному из условий.

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

    $$('.headParagraph').each(function(element, index){
    	element.addEvent('click',function(){
    		var myEffect = new Fx.Morph(element, {
                    duration: 'short', 
                    transition: Fx.Transitions.Elastic.easeInOut
                    });
    		myEffect.start('.selected');
    		$$('.headParagraph').each(function(otherElement, otherIndex){
    			if(element!=otherElement){
    				var myOtherEffect = new Fx.Morph(otherElement, {
                                    duration: 'short', 
                                    transition: Fx.Transitions.Back.easeOut
                                    });
    				myOtherEffect.start('.headParagraph');
    			}
    		});
    	});
    });


    Необходимо отметить, что конструкция $$('.headParagraph').each(function(element, index){...}); перебирает поочередно все элементы массива $$('.headParagraph'), присваивая переменной element значение текущего элемента массива, а переменной index — ключ этого элемента.
    Разберем немного подробнее код, который я привел выше. Каждому элементу в цикле к событию onClick мы привязываем анимацию:

    element.addEvent('click',function(){
        var myEffect = new Fx.Morph(element, {
            duration: 'short', 
            transition: Fx.Transitions.Elastic.easeInOut
        });
        myEffect.start('.selected');
        …
    });


    А конструкция

    $$('.headParagraph').each(function(otherElement, otherIndex){
        if(element!=otherElement){
            var myOtherEffect = new Fx.Morph(otherElement, {
                duration: 'short', 
                transition: Fx.Transitions.Back.easeOut
            });
            myOtherEffect.start('.headParagraph');
        }
    });


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

    Конечный результат можно увидеть по этой ссылке.

    Если у вас появятся какие-либо вопросы, с радостью готов на них ответить в комментариях или по хабрапочте. Ну а если читателей заинтересует данная тематика, то продолжение не заставит себя долго ждать.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      0
      Да, кстати, буду рад, если вы будете оставлять отзывы о качестве статьи (:
        +1
        У вас очень удачно получилось вписать длинную строку кода в дизайн хабра.
        картинка большая, так что только ссылка
          0
          Ой, спасибо что сказали, сейчас же исправлю
            0
            А на моём мониторе и так отлично =)
              0
              На мем тоже было, я думал хабр автоматически перенесет строку )):
          0
          а если запоминать выбранный элемент, то потом не надо будет бегать по всему меню =) а только ему поменять класс на «не выбранный»
          0
          duration может быть задан не только как 'long' или 'short', но и в миллисекундах, естественно.
            +1
            Html-код можно было «посемантичней» написать.
              –2
              А что в Вашем понятии «семантика» в вебе, позвольте поинтересоваться?
                0
                Читайте мат часть.

                P.S. В данном случае — использование списка для навигации.
                  0
                  Читайте мат часть учите матчасть.
                  Я представляю себе что такое семантика, хоть и весьма смутно, а потому и прошу просвятить меня в этом вопросе. Почему-то все, кого ни спроси, отвечают в таком духе. А что дает эта семантика? И мне не интересны цитаты с википедии. Мне интересна практическая сторона этого вопроса. В частности: почему, например, навигация должна быть списком? Тем более в данном случае — это лишние данные, а следовательно и больший объем загружаемого файла. Это если один список такой ничего не заметно, а если их много больше?
                    0
                    Согласен с вашим недовольством. Для меня семантика — использование элементов разметки, название которых соответствует их содержанию. Вполне просто на мой взгляд. Ведь css позволяет сделать из того же «b» сделать ячейку таблицы или параграф, только вот зачем?

                    P.S. о целесообразности списков читайте ниже.
                    0
                    А вот интересно, почему навигации семантически близок список, а не, скажем, абзац?
                    Ссылки вроде бы идут списком? Ну так и абзацы, и главы идут списком, один за другим.
                      0
                      Отключите стили, например. При использовании списков вложенное меню будет отображаться вполне адекватно.
                        0
                        Угу, как идущие один за другим пункты с буллетами — это адекватно чему? Если заключать не в список, а в абзацы например — получатс идущий один за другим пункты без буллетов. Кроме буллетов — никакой разницы.
                –2
                2автор: «Итак», «также» // F7 в word`е.
                  0
                  Спасибо! Все отлично!
                  Просто и понятно. Идея в упавшем меню тоже забавна.
                    +1
                    Отлично! Давайте же наполним блог MooTools качественными статьями.

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

                    Самое читаемое