Как заставить сработать условие, после добавление класса
Доброго времени суток. Проблема следующая: есть блок, изначально его позиция скрыта от визуального контакта right: -300, при клике, к блоку подключается class "mobile-menu--active", после чего его позиция должна равняться right: 0, но этого не происходит. Как исправить это, условие вроде написано правильно, но мне кажется оно срабатывает один раз и дальше не проверяется, как отследить добавление нового класса и проиграть условие повторно? Не судите строго, я только учусь:)
(function($) { $.fn.mobileMenu = function(options) { //Defaults to extend options var settings = { side: 'right', width: 300, animationSpeed: 600 }; //Extend those options var options = $.extend(settings, options); return this.each(function () { var mob = $(this), mobMenu = $('.mobile-menu'); mob.on('click touchend', function () { if(mobMenu.is('.mobile-menu--active')) { mobMenu.removeClass('mobile-menu--active'); $('.hamburger--active').removeClass('hamburger--active'); } else { mobMenu.addClass('mobile-menu--active'); mob.addClass('hamburger--active'); } return false; }); /////// ANIMATION var rightSide = 'mobile-menu--right-side', leftSide = 'mobile-menu--left-side', topSide = 'mobile-menu--top-side'; if(options.side == "right") { mobMenu .addClass(rightSide) .css({"right": - options.width, "z-index" : 3}); if (mobMenu.is('mobile-menu--active')) { mobMenu .animate({"right": 0}, options.animationSpeed); } } }); //each call }; //mobileMenu plugin })(jQuery); |
Luther,
строки 29 - 30 перенести в начало строки 47, если не поможет, делайте макет. [html run] ... минимальный код страницы с вашей проблемой [/html] О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting. |
Перенес как вы сказали, не помогло, прикрепляю код, надеюсь все правильно сделал.
<!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> .hamburger {width: 20px;height: 20px;background-color: red} .hamburger--active {background-color: green} .mobile-menu {position: fixed;width: 100%;max-width: 300px;height: 100%; top: 0} </style> </head> <body> <div class="hamburger"> </div> <div class="mobile-menu"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { //Defaults to extend options var settings = { side: 'right', width: 300, animationSpeed: 600 }; //Extend those options var options = $.extend(settings, options); return this.each(function () { var mob = $(this), mobMenu = $('.mobile-menu'); mob.on('click touchend', function () { if(mobMenu.is('.mobile-menu--active')) { mobMenu.removeClass('mobile-menu--active'); $('.hamburger--active').removeClass('hamburger--active'); } else { mobMenu.addClass('mobile-menu--active'); mob.addClass('hamburger--active'); } return false; }); /////// ANIMATION var rightSide = 'mobile-menu--right-side', leftSide = 'mobile-menu--left-side', topSide = 'mobile-menu--top-side'; if(options.side == "right") { mobMenu .addClass(rightSide) .css({"right": - options.width, "z-index" : 3}); if (mobMenu.is('mobile-menu--active')) { mobMenu .animate({"right": 0}, options.animationSpeed); } } }); //each call }; //mobileMenu plugin })(jQuery); $('.hamburger').mobileMenu({ }); </script> </body> </html> |
Luther, у вас же не css анимация, а изменение класса, это асинхронное событие. Тогда сразу по смене класса и выполняйте анимацию:
(function($) { $.fn.mobileMenu = function(options) { var settings = { side: 'right', width: 300, animationSpeed: 600 }; //Extend those options var options = $.extend(settings, options); return this.each(function () { var mob = $(this), mobMenu = $('.mobile-menu'); mob.on('click touchend', function () { mobMenu.toggleClass('mobile-menu--active'); mob.toggleClass('hamburger--active'); mobMenu.animate({right: -options.width + mob.is('.hamburger--active') * options.width}, options.animationSpeed); }); }); }; })(jQuery); $('.hamburger').mobileMenu(); |
Цитата:
Оказывается это было проще, чем то что я варганил, спасибо большое за помощь, все работает |
Цитата:
<!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> .hamburger-button {width: 20px;height: 20px;background-color: red} .hamburger--active {background-color: green} .hamburger { position: fixed; top: 20px; height: 100%; display: none; } </style> </head> <body> <div class="hamburger-button"> </div> <div class="hamburger"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { var settings = { side: 'right', width: 300, animationSpeed: 600, button: $('div.hamburger-button') }; var options = $.extend(settings, options), mobMenu = $(this); mobMenu.css({maxWidth: options.width, [options.side]: -options.width}).show(); //так определить в литеральном объекте свойство через переменную можно в ES6 return this.each(function () { options.button.on('click touchend', function () { options.button.toggleClass('hamburger--active'); //и только так определить в литеральном объекте свойство через переменную можно для старичков var opt = {}; opt[options.side] = -options.width + options.button.is('.hamburger--active') * options.width; mobMenu.animate(opt, options.animationSpeed); }); }); }; })(jQuery); $('div.hamburger').mobileMenu({side: 'left', width: 600}); </script> </body> </html> |
:) потом будет вопрос как закрыть по клику вне меню.
|
рони, :D
|
Цитата:
Только щас увидел и чет не очень понятно, но я сделал следующем образом, если интересно: <!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> .hamburger {width: 20px;height: 20px;background-color: red} .hamburger--active {background-color: green} .mobile-menu {position: fixed;height: 100%;top: 0;background-color: yellow} .overlay { left: 0; width: 100%; background-color: rgba(0,0,0,.4); position: fixed; top: 0; height: 100%; } </style> </head> <body> <div class="hamburger"> </div> <div class="mobile-menu"> <h1>Заголовок</h1> <p> Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Запятой lorem текста, первую ему ее, над родного. Если, алфавит ручеек коварный там города образ великий маленькая текстов вопроса он.</p> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { //Defaults to extend options var settings = { side: 'left', butClass: 'hamburger', butClassActive: 'hamburger--active', width: 300, // if puted (side: 'top'), there must be 100 zIndex: 99, exit: true, overlay: true, animationSpeed: 400, // afterChange: function(){} }; //Extend those options var options = $.extend(settings, options); return this.each(function () { var mob = $(this), btn = $('.' + options.butClass), mobMenu = $('.mobile-menu'), mobMenuActive = 'mobile-menu--active'; var rightSide = 'mobile-menu--right-side', leftSide = 'mobile-menu--left-side', topSide = 'mobile-menu--top-side'; if (options.side == 'right') { mobMenu.addClass(rightSide).css({right: -options.width, width: options.width, 'z-index': options.zIndex}); } if (options.side == 'left') { mobMenu.addClass(leftSide).css({left: -options.width, width: options.width, 'z-index': options.zIndex}); } if (options.side == 'top') { mobMenu.addClass(topSide).css({top: -options.width+'%', width: options.width+'%', 'z-index': options.zIndex}); } function moveMenu() { if (options.side == 'right') { $('.' + rightSide).animate({right: -options.width + mob.hasClass(options.butClassActive) * options.width}, options.animationSpeed); } if (options.side == 'left') { $('.' + leftSide).animate({left: -options.width + mob.hasClass(options.butClassActive) * options.width}, options.animationSpeed); } if (options.side == 'top') { $('.' + topSide).animate({top: -options.width + mob.hasClass(options.butClassActive) * options.width+'%'}, options.animationSpeed); } } if (options.overlay) { if (options.overlay == "false") { return false; } var directionalOverlayHTML = '<div class="overlay"></div>'; mobMenu.before(directionalOverlayHTML); var bgOverlay = $('div.overlay'); bgOverlay.hide().css({'z-index': options.zIndex - 1}); } mob.on('click touchend', function () { mobMenu.stop().toggleClass(mobMenuActive); btn.stop().toggleClass(options.butClassActive); if (options.overlay) { if(options.overlay == "false") { return false; } if (mobMenu.hasClass(mobMenuActive)) { if (btn.hasClass(options.butClassActive)) { bgOverlay.fadeIn(options.animationSpeed); bgOverlay.on('click touchend', function () { mobMenu.stop().removeClass(mobMenuActive); btn.stop().removeClass(options.butClassActive); bgOverlay.fadeOut(options.animationSpeed); moveMenu(); }); } } } moveMenu(); }); if (options.exit) { if(options.exit == "false") { return false; } var directionalExitHTML = '<div class="mobile-menu-inner"><span class="mobile-menu__exit">exit</span></div>'; mobMenu.append(directionalExitHTML); var exitBtn = mobMenu.children('div.mobile-menu-inner').children('span.mobile-menu__exit'); exitBtn.on('click touchend', function () { mobMenu.stop().removeClass(mobMenuActive); btn.stop().removeClass(options.butClassActive); moveMenu(); if (options.overlay) { if(options.overlay == "false") { return false; } bgOverlay.fadeOut(options.animationSpeed); } }); } $(document).keyup(function(esc) { if (esc.keyCode === 27) { if (mobMenu.hasClass(mobMenuActive)) { if (btn.hasClass(options.butClassActive)) { mobMenu.stop().removeClass(mobMenuActive); btn.stop().removeClass(options.butClassActive); moveMenu(); if (options.overlay) { if(options.overlay == "false") { return false; } bgOverlay.fadeOut(options.animationSpeed); } } } } }); }); //each call }; //mobileMenu plugin })(jQuery); $('.hamburger').mobileMenu(); </script> </body> </html>[/quote] Да, я думаю код в некоторых местах некорректный, ну как получается, сейчас пытаюсь настроить анимацию так чтоб она не прыгала, при многократном нажатии, добавил .stop(), но работает не очень привлекательно, как можно сделать, чтоб анимация проигрывалась до конца, а не постоянно обрабатывалась? + еще надо , чтобы на .hamburger вешался класс .hamburger--active только после того как анимация проигралась, ну т.е. Зеленой, кнопка должна стать, только когда меню окончательно выдвинулось |
Зачем 'z-index': options.zIndex все время определять, а не единожды? Выполните для позиции лево/верх, и сразу будет виден баг. И почему вы упорно определяете кнопку управления как целевой объект для плагина вместо самого меню?
И лишнего много. |
|
Luther, надо определиться с кнопкой, а сколько классов и зачем добавлять меню, это уже вторично. Меню можно и снизу/вверх, сверху/вниз, слева/направо, справа/налево сдвигать по одному и тому же принципу, его начальная позиция и будет определять все параметры, как то классы меню которые вы описываете, и положение кнопки, и для этого описаний условий if(...) ... не потребуется, проще взять определения из объекта. Положение кнопки для того, чтобы к примеру она перекрывала меню, и ее положение зависело от исходного положения меню как тут:
<!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> html,body { height: 100%; margin: 0; } .hamburger-button { display: none; position: fixed; top: 20px; width: 30px; height: 30px; cursor: pointer; z-index: 1; } .button-bar1, .button-bar2, .button-bar3 { width: 30px; height: 5px; margin: 0 0 5px; background-color: #888; } .hamburger--active .button-bar1 { background-color: #fff; transform: rotate(-45deg) translate(-8px, 7px); } .hamburger--active .button-bar2 { opacity: 0; } .hamburger--active .button-bar3 { background-color: #fff; transform: rotate(45deg) translate(-7px, -7px); } .hamburger { position: fixed; height: 100%; top: 0; display: none; background-color: #999; padding: 20px; box-sizing: border-box } </style> </head> <body> <div class="hamburger-button"> <div class="button-bar1"></div> <div class="button-bar2"></div> <div class="button-bar3"></div> </div> <div class="hamburger"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> </div> <script> </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { var settings = { side: 'right', width: 300, animationSpeed: 600, zIndex: 100, button: '.hamburger-button', classActive: 'hamburger--active' }, options = $.extend(settings, options), mobMenu = $(this), bt = $(options.button); mobMenu.css({maxWidth: options.width, [options.side]: -options.width, zIndex: options.zIndex}).show(); bt.css({top: mobMenu.css('padding-top'), [options.side]: mobMenu.css('padding-top'), zIndex: options.zIndex+1}).show().children().css({transition: options.animationSpeed/1000 + 's'}); $(document).on('click', function(e) { e = $(e.target); if(!parseInt(mobMenu[0].style[options.side]) && !(e.closest(mobMenu).length || e.hasClass(options.classActive))) bt.trigger('click', [1]); }); return this.each(function () { bt.on('click touchend', function (e, c) { e.stopPropagation(); bt.toggleClass(options.classActive); mobMenu.animate({[options.side]: -options.width + (c ? 0 : bt.hasClass(options.classActive)) * options.width}, options.animationSpeed); }) }); }; })(jQuery); $('div.hamburger').mobileMenu({side: 'left', width: 400}); </script> </body> </html> Но если направление вверх/вниз, то вряд ли разумно options.width+'%', скорее всего высота меню должна при инициализации получать высоту клиентской области, ее же и при изменении размеров окна. Изменять класс кнопки после окончания анимации меню, это еще вопрос нужно ли, то есть определитесь окончательно со всем, тогда и остальное будет видно. |
Цитата:
Ваш код отлично выглядит, работает тоже прекрасно, завтра буду разбираться, большое спасибо что помогаете |
Ну в таком случае, кнопку меню можно также сдвигать к краю, влево/вправо в зависимости от положения меню. При этом ее анимацию (open/close) и анимацию движения можно задерживать, а к движению применять различные временные характеристики анимации.
В коде в литеральном объекте свойство определяется как в E6, о чем говорилось выше. Но, к примеру, если сжать код, например этим, то в итоге все будет отвечать и старичкам, тут как раз итог сжатия. А в коде приведенном ранее добавление и изменение после bt = $(options.button) добавлено объявление p = mobMenu.css('padding-top'), изменено bt.css({top: p, [options.side]: p, zIndex: options.zIndex+1}).show().children().css({transition: options.animationSpeed/1000 + 's'}); В обработчик bt.on('click touchend' ... добавлено: var r = parseInt(p); bt.toggleClass(options.classActive).delay(50).animate({[options.side]: r + (options.width - (r*3.5)) * (c ? 0 : bt.hasClass(options.classActive))}, options.animationSpeed); <!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> html,body { height: 100%; margin: 0; } .hamburger-button { display: none; position: fixed; top: 20px; width: 30px; height: 30px; cursor: pointer; z-index: 1; } .button-bar1, .button-bar2, .button-bar3 { width: 30px; height: 5px; margin: 0 0 5px; background-color: #888; transition-delay: .3s } .hamburger--active .button-bar1 { background-color: #fff; transform: rotate(-45deg) translate(-8px, 7px); } .hamburger--active .button-bar2 { opacity: 0; } .hamburger--active .button-bar3 { background-color: #fff; transform: rotate(45deg) translate(-7px, -7px); } .hamburger { position: fixed; height: 100%; top: 0; display: none; background-color: #999; padding: 20px; box-sizing: border-box } </style> </head> <body> <div class="hamburger-button"> <div class="button-bar1"></div> <div class="button-bar2"></div> <div class="button-bar3"></div> </div> <div class="hamburger"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> </div> <script> </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function(c){c.fn.mobileMenu=function(a){a=c.extend({side:"right",width:300,animationSpeed:600,zIndex:100,button:".hamburger-button",classActive:"hamburger--active"},a);var e=c(this),d=c(a.button),g=e.css("padding-top"),b={};e.css((b.maxWidth=a.width,b[a.side]=-a.width,b.zIndex=a.zIndex,b)).show();b={};d.css((b.top=g,b[a.side]=g,b.zIndex=a.zIndex+1,b)).show().children().css({transition:a.animationSpeed/1E3+"s"});c(document).on("click",function(b){b=c(b.target);parseInt(e[0].style[a.side])||b.closest(e).length||b.hasClass(a.classActive)||d.trigger("click",[1])});return this.each(function(){d.on("click touchend",function(b,c){b.stopPropagation();var f=parseInt(g),h={};d.toggleClass(a.classActive).delay(50).animate((h[a.side]=f+(a.width-3.5*f)*(c?0:d.hasClass(a.classActive)),h),a.animationSpeed);f={};e.animate((f[a.side]=-a.width+(c?0:d.hasClass(a.classActive))*a.width,f),a.animationSpeed)})})}})(jQuery); $('div.hamburger').mobileMenu({width: 400}); </script> </body> </html> |
Luther,
не копируйте сообщение целиком без необходимости, есть цитирование выделенного фрагмента. |
Цитата:
if(!parseInt(mobMenu[0].style[options.side]) && !(e.closest(mobMenu).length || e.hasClass(options.classActive))) bt.trigger('click', [1]);Не могли бы вы объяснить ее? И я буду немного дорабаывать/переделывать, кнопка будет оставаться на своем месте и не налазить на меню, но ее анимация должна проигрываться, но только после открытия меню или закрытия, а в самом меню сделать дополнительную кнопку закрытия. Спасибо что помогаете |
Цитата:
Цитата:
|
Это закрытие меню при клике вне его. Здесь запускается событие click кнопки, в обработчик которого передается параметр 1. Это произойдет если меню раскрыто (!parseInt(mobMenu[0].style[options.side])) И источник не принадлежит меню (e.closest(mobMenu).length) ИЛИ это не кнопка меню (e.hasClass(options.classActive)).
В обработчике меню сдвигается от исходного положения (side) в направлении рассчитанным: для кнопки: отступ меню + (ширина меню - отступ меню*3.5) * направление определяемое условием щелчка вне меню либо состоянием кнопки меню для меню: отрицательная ширина меню + направление определяемое условием щелчка вне меню либо состоянием кнопки меню * ширина меню Направление определяемое условием щелчка вне меню либо состоянием кнопки меню * ширина меню = c ? 0 : bt.hasClass(options.classActive). Можно в триггере в обработчик передавать значение -1, тогда это условие можно записать так: c || bt.hasClass(options.classActive) но в этом случае будет погрешность в 1px при сдвиге меню (можете вывести в консоль, поймете). Если результат выводить в консоль, то станет понятна вся эта арифметика, получение -NNN или 0 для меню и NNN или 20 для кнопки. Для кнопки и меню одно и тоже условие, значит его можно определить сразу. Но определение будет до изменения состояния кнопки меню, следовательно в этом случае нужно брать отрицание состояния кнопки. return this.each(function () { bt.on('click touchend', function (e, c) { e.stopPropagation(); var r = parseInt(p), dir = c ? 0 : !bt.hasClass(options.classActive); //направление в анимации bt.toggleClass(options.classActive).delay(50).animate({[options.side]: r + (options.width - r*3.5) * dir}, options.animationSpeed); mobMenu.animate({[options.side]: -options.width + dir * options.width}, options.animationSpeed); }) }); Это пример, и в примере время анимации состояния кнопки определяется временем анимации меню. Но на мой взгляд, если принять такое поведение меню, то за время анимации меню кнопка должна только сдвигаться к краю и изменять цвет, а после этого уже анимация состояния кнопки. Это пример и в нем все упрощено, у вас же все написано так, что ... ) На Хабре, да и не только на нем, можно найти статьи о создании плагинов в jQ, там описано как это грамотно сделать - параметры, инициализация, методы. |
Цитата:
var exit = $(options.exit); $(document).keyup(function (e) { if(e.keyCode === 27 && !parseInt(mobMenu[0].style[options.side])) bt.trigger('click', [1]); }); exit.on('click', function (e) { e = $(e.target); if(!parseInt(mobMenu[0].style[options.side])) bt.trigger('click', [1]); }); Работает, только приходиться дублировать, есть ли возможность объединения? |
Цитата:
|
Цитата:
.hamburger--animate .button-bar1 { background-color: #fff; transform: rotate(-45deg) translate(-8px, 7px); } .hamburger--animate .button-bar2 { opacity: 0; } .hamburger--animate .button-bar3 { background-color: #fff; transform: rotate(45deg) translate(-7px, -7px); } которые добавляются им на определенном шаге анимации меню. При определении объектов определяем для меню данные, ну и запуск в шаге: mobMenu = $(this).data({end: 1}) bt.on('click touchend', function (e, c) { e.stopPropagation(); var dir = c ? 0 : !bt.hasClass(options.classActive); //направление в анимации bt.toggleClass(options.classActive) mobMenu.animate({[options.side]: -options.width + options.width * dir}, { duration: options.animationSpeed, step: function(pos, f) { var v = f.start + f.end, d = dir ? v - v * .3 //старт анимации кнопки при открытии : v * .5; //старт анимации кнопки при закрытии if($(this).data('end') && pos > d) { bt.toggleClass('hamburger--animate'); //включаем анимацию/возвращаем в начало $(this).data({end: 0}) //более не реагируем на изменения } }, complete: function(f) { $(this).data({end: 1}) //разрешаем запуск анимации кнопки } }); }) Плюс различные временные характеристики анимации доступны, и тогда все может получится, по крайней мере лучше, чем по окончании анимации меню, на мой взгляд. |
Цитата:
mobMenu.toggleClass(mobActive).stop().animate({[options.side]: -options.width + (c ? 0 : mobMenu.hasClass(mobActive)) * options.width}, {complete: function() {bt.toggleClass(btActive)}}, options.animationSpeed); Но, все равно, это не так как нужно, потому что при многократном клике, кнопка будет меняться, не смотря на то что меню еще не сработало. В общем, вот как сейчас все выглядит, нужно только с кнопкой разобраться, а так все в порядке думаю <!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> html,body { height: 100%; margin: 0; } .hamburger{ position: fixed; top: 20px; width: 30px; height: 30px; cursor: pointer; z-index: 1; transition: all .25s ease; } .button-bar1, .button-bar2, .button-bar3 { width: 30px; height: 5px; margin: 0 0 5px; background-color: #888; transition: all .25s ease; } .hamburger--active .button-bar1 { transform: rotate(-45deg) translate(-8px, 7px); } .hamburger--active .button-bar2 { opacity: 0; } .hamburger--active .button-bar3 { transform: rotate(45deg) translate(-7px, -7px); } .mobile-menu { position: fixed; height: 100%; top: 0; display: none; background-color: #999; padding: 20px; box-sizing: border-box } </style> </head> <body> <div class="hamburger"> <div class="button-bar1"></div> <div class="button-bar2"></div> <div class="button-bar3"></div> </div> <div class="mobile-menu"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> <div class="exit">Выйти</div> </div> <script> </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { var settings = { side: 'right', width: 300, animationSpeed: 600, zIndex: 100, exit: '.exit', button: 'hamburger', classActive: '--active' }, options = $.extend(settings, options), mobMenu = $(this).data({end: 1}), bt = $('.' + options.button), mobActive = mobMenu.attr('class').split(' ')[0] + options.classActive, btActive = bt.attr('class').split(' ')[0] + options.classActive, exit = $(options.exit); mobMenu.css({maxWidth: options.width, [options.side]: -options.width, zIndex: options.zIndex}).show(); $(document).on('click', function(e) { e = $(e.target); if(!parseInt(mobMenu[0].style[options.side]) && !(e.closest(mobMenu).length || e.hasClass(mobActive))) bt.trigger('click', [1]); }); $(document).keyup(function (e) { if(e.keyCode === 27 && !parseInt(mobMenu[0].style[options.side])) bt.trigger('click', [1]); }); exit.on('click', function (e) { e = $(e.target); if(!parseInt(mobMenu[0].style[options.side])) bt.trigger('click', [1]); }); return this.each(function () { bt.on('click touchend', function (e, c) { e.stopPropagation(); mobMenu.toggleClass(mobActive).stop().animate({[options.side]: -options.width + (c ? 0 : mobMenu.hasClass(mobActive)) * options.width}, {complete: function() {bt.toggleClass(btActive)}}, options.animationSpeed); }) }); }; })(jQuery); $('div.mobile-menu').mobileMenu({side: 'right', width: 400}); </script> </body> </html> |
Цитата:
<!DOCTYPE html> <html lang="ru"> <html> <head> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> html,body { height: 100%; margin: 0; } .hamburger-button { display: none; position: fixed; top: 20px; width: 30px; height: 30px; cursor: pointer; z-index: 1; } .button-bar1, .button-bar2, .button-bar3 { width: 30px; height: 5px; margin: 0 0 5px; background-color: #777; transition: .6s } .hamburger--animate .button-bar1 { background-color: #fff; transform: rotate(-45deg) translate(-8px, 7px); } .hamburger--animate .button-bar2 { opacity: 0; } .hamburger--animate .button-bar3 { background-color: #fff; transform: rotate(45deg) translate(-7px, -7px); } .hamburger { position: fixed; height: 100%; top: 0; display: none; background-color: #999; padding: 20px; box-sizing: border-box } </style> </head> <body> <div class="hamburger-button"> <div class="button-bar1"></div> <div class="button-bar2"></div> <div class="button-bar3"></div> </div> <div class="hamburger"> <h1>Заголовок блока</h1> <p>Далеко-далеко за словесными горами в стране, гласных и согласных живут рыбные тексты. Проектах знаках переулка курсивных снова журчит жизни все приставка безопасную!</p> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> (function($) { $.fn.mobileMenu = function(options) { var settings = { side: 'right', width: 300, animationSpeed: 600, zIndex: 100, esc: true, button: '.hamburger-button', classActive: 'hamburger--active', classAnimateButton: 'hamburger--animate' }, options = $.extend(settings, options), mobMenu = $(this).data({end: 1}), bt = $(options.button), p = mobMenu.css('padding-top'); mobMenu.css({maxWidth: options.width, [options.side]: -options.width, zIndex: options.zIndex}).show(); bt.css({top: p, [options.side]: p, zIndex: options.zIndex+1}).show(); $(document).on('click.hamburger touchend.hamburger', function(e, d) { e = $(e.target); if(!parseInt(mobMenu[0].style[options.side]) && !(e.closest(mobMenu).length || e.is(bt) || d)) bt.trigger('click', [1]); }); if(options.esc) $(document).on('keyup.hamburger', function(e) { if(e.keyCode === 27) $(this).trigger('click.hamburger', [0]); }); return this.each(function () { bt.on('click touchend', function (e, c) { e.stopPropagation(); var dir = c ? 0 : !mobMenu.hasClass(options.classActive); //направление в анимации mobMenu.toggleClass(options.classActive).animate({[options.side]: -options.width + options.width * dir}, { duration: options.animationSpeed, step: function(pos, f) { var v = f.start + f.end, d = dir ? v - v * .5 //старт анимации кнопки при открытии : v * .7; //старт анимации кнопки при закрытии if($(this).data('end') && pos > d) { bt.toggleClass(options.classAnimateButton); //включаем анимацию/возвращаем в начало $(this).data({end: 0}) //более не реагируем на изменения } }, complete: function(f) { $(this).data({end: 1}) //разрешаем запуск анимации } }); }) }); }; })(jQuery); $('div.hamburger').mobileMenu({width: 400}); </script> </body> </html> Пощелкайте многократно на кнопку, наблюдайте, анализируйте. Если кнопка у вас не будет перекрывать меню, находится от него в противоположной стороне (где же ей место при side: top тогда :) ), то конечно анимацию ее можно начитать и при окончании анимации меню, взгляд то при этом будет фиксирован только на одном элементе. События на таких объектах как документ разделяйте пространством имен, указывая их и в триггерах. |
Цитата:
|
При фиксированном положении кнопки?
|
Цитата:
|
Тогда в опциях вместо width можно определять размер size. Если side при этом будет left/right, значит это будет и ширина меню, а высота 100%, иначе это будет высота меню и ширина 100%. А математика расчета куда двигаем останется прежней, только уже не для width, а для size:
side = -size + size * dir |
Понял, попробую сегодня, спасибо большое за весь ваш труд, очень помогли. А следующий плагин у меня по списку - слайдер :)
|
laimas, а почему анимация не гладкая? (Потому что там нет анимации, а только несинхронизированное обновление стилей!)
Почему на телефоне или сенсорном экране меню как открывается, так и сразу закрывается? (Потому что touchend) Почему 130 строк вместо пары десятков? (Потому что девиз от jQuery «Write less do more» лжив, и эта религия запрещает вам использовать современные наработки) |
Часовой пояс GMT +3, время: 23:55. |