12.11.2019, 01:19
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
|
|
12.11.2019, 01:56
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
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+'%', скорее всего высота меню должна при инициализации получать высоту клиентской области, ее же и при изменении размеров окна. Изменять класс кнопки после окончания анимации меню, это еще вопрос нужно ли, то есть определитесь окончательно со всем, тогда и остальное будет видно.
Последний раз редактировалось laimas, 12.11.2019 в 02:15.
|
|
12.11.2019, 03:12
|
Интересующийся
|
|
Регистрация: 11.11.2019
Сообщений: 12
|
|
Сообщение от laimas
|
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+'%', скорее всего высота меню должна при инициализации получать высоту клиентской области, ее же и при изменении размеров окна. Изменять класс кнопки после окончания анимации меню, это еще вопрос нужно ли, то есть определитесь окончательно со всем, тогда и остальное будет видно.
|
Ваш код отлично выглядит, работает тоже прекрасно, завтра буду разбираться, большое спасибо что помогаете
|
|
12.11.2019, 03:48
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Ну в таком случае, кнопку меню можно также сдвигать к краю, влево/вправо в зависимости от положения меню. При этом ее анимацию (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>
|
|
12.11.2019, 07:57
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
Luther,
не копируйте сообщение целиком без необходимости, есть цитирование выделенного фрагмента.
|
|
12.11.2019, 14:38
|
Интересующийся
|
|
Регистрация: 11.11.2019
Сообщений: 12
|
|
Сообщение от laimas
|
$(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]);
});
|
Здравствуйте, да код отличный, пытаюсь разобраться, вопрос вызывает эта функция, а именно строчка:
if(!parseInt(mobMenu[0].style[options.side]) && !(e.closest(mobMenu).length || e.hasClass(options.classActive))) bt.trigger('click', [1]);
Не могли бы вы объяснить ее? И я буду немного дорабаывать/переделывать, кнопка будет оставаться на своем месте и не налазить на меню, но ее анимация должна проигрываться, но только после открытия меню или закрытия, а в самом меню сделать дополнительную кнопку закрытия. Спасибо что помогаете
|
|
12.11.2019, 14:54
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
Сообщение от Luther
|
но ее анимация должна проигрываться, но только после открытия меню или закрытия,
|
.animate( properties [, duration ] [, easing ] [, complete ] )
Цитата:
|
функция, которая будет вызвана после завершения анимации.
|
|
|
12.11.2019, 15:21
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Это закрытие меню при клике вне его. Здесь запускается событие 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, там описано как это грамотно сделать - параметры, инициализация, методы.
Последний раз редактировалось laimas, 12.11.2019 в 15:58.
|
|
12.11.2019, 16:19
|
Интересующийся
|
|
Регистрация: 11.11.2019
Сообщений: 12
|
|
Сообщение от laimas
|
Это закрытие меню при клике вне его. Здесь запускается событие click кнопки, в обработчик которого передается параметр 1. Это произойдет если меню раскрыто (!parseInt(mobMenu[0].style[options.side])) И источник не принадлежит меню (e.closest(mobMenu).length) ИЛИ это не кнопка меню (e.hasClass(options.classActive)).
.
|
Спасибо за объяснение, добавил по аналогу еще 2 функции
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]);
});
Работает, только приходиться дублировать, есть ли возможность объединения?
|
|
12.11.2019, 16:21
|
Интересующийся
|
|
Регистрация: 11.11.2019
Сообщений: 12
|
|
Сообщение от рони
|
.animate( properties [, duration ] [, easing ] [, complete ] )
|
Спасибо, попробую этот способ
|
|
|
|