Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 12.11.2019, 18:29
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от Luther
приходиться дублировать, есть ли возможность объединения?
Можно и одним обработчиком, в нем ведь будет известен и тип события, и его источник. В какофонии сообщений я не заметил этого "кнопка будет оставаться на своем месте и не налазить на меню, но ее анимация должна проигрываться, но только после открытия меню или закрытия". Не проблема, но наверное ее лучше запускать с определенного шага анимации (step), а не в конце ее. Например, пусть запуск анимации, это наличие класса 'hamburger--animate' у дочерних элементов кнопки, то есть:

.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}) //разрешаем запуск анимации кнопки
                }
            });
                
        })


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

Последний раз редактировалось laimas, 12.11.2019 в 18:34.
Ответить с цитированием
  #22 (permalink)  
Старый 12.11.2019, 21:48
Интересующийся
Отправить личное сообщение для Luther Посмотреть профиль Найти все сообщения от Luther
 
Регистрация: 11.11.2019
Сообщений: 12

Сообщение от laimas Посмотреть сообщение
Можно и одним обработчиком, в нем ведь будет известен и тип события, и его источник. В какофонии сообщений я не заметил этого "кнопка будет оставаться на своем месте и не налазить на меню, но ее анимация должна проигрываться, но только после открытия меню или закрытия". Не проблема, но наверное ее лучше запускать с определенного шага анимации (step), а не в конце ее. Например, пусть запуск анимации, это наличие класса 'hamburger--animate' у дочерних элементов кнопки, то есть:
Этот способ почему то не сработал, сделал пока что так
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>

Последний раз редактировалось Luther, 12.11.2019 в 21:52.
Ответить с цитированием
  #23 (permalink)  
Старый 12.11.2019, 22:27
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от Luther
Но, все равно, это не так как нужно, потому что при многократном клике ...
<!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 тогда ), то конечно анимацию ее можно начитать и при окончании анимации меню, взгляд то при этом будет фиксирован только на одном элементе.

События на таких объектах как документ разделяйте пространством имен, указывая их и в триггерах.
Ответить с цитированием
  #24 (permalink)  
Старый 13.11.2019, 01:15
Интересующийся
Отправить личное сообщение для Luther Посмотреть профиль Найти все сообщения от Luther
 
Регистрация: 11.11.2019
Сообщений: 12

Сообщение от laimas Посмотреть сообщение
[HTML run hide height=400]<!DOCTYPE html>

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

События на таких объектах как документ разделяйте пространством имен, указывая их и в триггерах.
Ладно с этим я уже разберусь, последнее что хочу спросить, как теперь мне правильно построить условие, если: side: 'top' ?
Ответить с цитированием
  #25 (permalink)  
Старый 13.11.2019, 05:03
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

При фиксированном положении кнопки?
Ответить с цитированием
  #26 (permalink)  
Старый 13.11.2019, 10:32
Интересующийся
Отправить личное сообщение для Luther Посмотреть профиль Найти все сообщения от Luther
 
Регистрация: 11.11.2019
Сообщений: 12

Сообщение от laimas Посмотреть сообщение
При фиксированном положении кнопки?
Да
Ответить с цитированием
  #27 (permalink)  
Старый 13.11.2019, 10:50
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Тогда в опциях вместо width можно определять размер size. Если side при этом будет left/right, значит это будет и ширина меню, а высота 100%, иначе это будет высота меню и ширина 100%. А математика расчета куда двигаем останется прежней, только уже не для width, а для size:

side = -size + size * dir
Ответить с цитированием
  #28 (permalink)  
Старый 13.11.2019, 11:01
Интересующийся
Отправить личное сообщение для Luther Посмотреть профиль Найти все сообщения от Luther
 
Регистрация: 11.11.2019
Сообщений: 12

Понял, попробую сегодня, спасибо большое за весь ваш труд, очень помогли. А следующий плагин у меня по списку - слайдер
Ответить с цитированием
  #29 (permalink)  
Старый 13.11.2019, 11:20
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

laimas, а почему анимация не гладкая? (Потому что там нет анимации, а только несинхронизированное обновление стилей!)

Почему на телефоне или сенсорном экране меню как открывается, так и сразу закрывается? (Потому что touchend)

Почему 130 строк вместо пары десятков? (Потому что девиз от jQuery «Write less do more» лжив, и эта религия запрещает вам использовать современные наработки)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
переманную как условие в if блок xas Общие вопросы Javascript 3 02.02.2016 21:17
Добавление класса всем родительским элементам списка Torawhite Элементы интерфейса 0 01.05.2015 22:06
Сохранение данных после закрытия страницы HekracoB AJAX и COMET 12 02.01.2015 12:41
как заставить событие при resize сработать с небольшой задержкой один раз? mitiya Общие вопросы Javascript 3 21.10.2012 20:00
Как заставить выполняться обработчик после всех имеющихся обработчиков данного элемен Анатолий Саратовцев jQuery 2 08.10.2012 18:49