Цитата:
.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, время: 16:13. |