События / таймеры
Здравствуйте!
Задача: необходимо, чтобы при нажатии на кнопку меню плавно из-под неё выезжало. При повторном нажатии или нажатии НЕ на неё - так же плавно "въезжало" в неё. jQuery по опр. причинам не подходит. Код ещё не доработан, в нём много шлака, строго его не судите: <head> <title> </title> <meta charset='utf-8'> <style> html, body{ height:100%; margin:0; padding:0; } #right_menu, li{ margin:0; padding:0; display:block; } #right_menu{ position:absolute; width:65px; height:125px; background-color:#cccccc; border:2px solid; border-color: #dddddd #bbbbbb #bbbbbb #dddddd; padding-left:50px; } li{ width:60px; height:25px; margin:5px; line-height:25px; font-family:arial, sans-serif; font-size:10pt; text-indent:5px; } li:hover{ background-color:navy; color:white; } #b{ position:absolute; top:50px; left:10px; } </style> </head> <body> <ul id='right_menu'> <li>Effect 1</li> <li>Effect 2</li> <li>Effect 3</li> <li>Effect 4</li> </ul> <input type='button' id='b' value = 'Click'> var flag = false; var menu=document.getElementById('right_menu'); //меню скрыто при загрузке стр-цы menu.style.display='none'; var button = document.getElementById('b'); button.onclick=function(event){ //меню будет появл-ся там, где щёлкнули правой кнопкой menu.style.left=parseInt(getComputedStyle(button).left)+'px'; menu.style.top=parseInt(getComputedStyle(button).top)+'px'; if(flag == false){ menu.style.display='block'; intr_show=setInterval(show,1); flag = true; }else{ intr_hide=setInterval(hide,1); document.body.onclick = setInterval(hide,1); //какой-то бред написан, но и без этой строки работает по-другому flag=false; } } function show(){ //показываем UL width = parseInt(getComputedStyle(menu).width); height = parseInt(getComputedStyle(menu).height); if(width >= 65 && height >= 125) {return} menu.style.width = (width + 1)+'px'; menu.style.height = (height + 1)+'px'; //показываем LI var lis = document.querySelectorAll('li'); for(var i=0; i<lis.length;i++){ widthLi = parseInt(getComputedStyle(lis[i]).width); heightLi = parseInt(getComputedStyle(lis[i]).height); if (widthLi == 60 && heightLi ==25) { lis[0].innerHTML = 'Effect 1'; lis[1].innerHTML = 'Effect 2'; lis[2].innerHTML = 'Effect 3'; lis[3].innerHTML = 'Effect 4'; return} //чтобы ф-ция не вып-яла лишних действий lis[i].style.width = (widthLi + 1)+'px'; lis[i].style.height = (heightLi + 1)+'px'; } } function hide(){ //прячем UL widthUl = parseInt(getComputedStyle(menu).width); /*не обязат-но глобальная, т.к. перезапись происх-ит в св-ве: menu.style.width, а width получаем из него же*/ heightUl = parseInt(getComputedStyle(menu).height); if (widthUl <= 0 && heightUl <=0) { menu.style.border = 'none'; return} //чтобы ф-ция не вып-яла лишних действий menu.style.width = (widthUl - 1)+'px'; menu.style.height = (heightUl - 1)+'px'; //прячем LI var lis = document.querySelectorAll('li'); for(var i=0; i<lis.length;i++){ widthLi = parseInt(getComputedStyle(lis[i]).width); heightLi = parseInt(getComputedStyle(lis[i]).height); if (widthLi == 0 && heightLi ==0) { /*lis[i].innerHTML = ''; не корректно, т.к. if сработает сначала для i=0, но после "обнуления" innerHTML стоит return, кот-ый выкинет из ф-ции. При след-ем её запуске цикл опять начнётся с 0 и return опять выкинет после lis[0].innerHTML = ''; . Выходит, что innerHTML обнулится лишь у 1го эл-та*/ for(var j=0; j<lis.length;j++){ lis[j].innerHTML = ''; } return} //чтобы ф-ция не вып-яла лишних действий lis[i].style.width = (widthLi - 1)+'px'; lis[i].style.height = (heightLi - 1)+'px'; console.log(getComputedStyle(lis[i]).width) } } Ф-ция show не работает, а hide срабатывает, но некорректно. Сказать по правде, я пока слаб в событиях и таймерах, а задание срочное. Поэтому даже не знаю, что тут можно сделать. |
Цитата:
|
|
Цитата:
Полностью согласен))) Да только это не от заказчика, а на курсах задали. |
Цитата:
Мне кажется, мой алгоритм в общем верен, просто из-за нехватки теор. знаний я где-то лажаю... |
Boolean_Type,
Вариант на основе темы Дёрганье при смене анимации <!DOCTYPE HTML> <html> <head> <title> </title> <meta charset='utf-8'> <style> html, body{ height:100%; margin:0; padding:0; } #right_menu, li{ margin:0; padding:0; display:block; } #right_menu{ overflow: hidden; width:70px; height:125px; background-color:#cccccc; border:2px solid; border-color: #dddddd #bbbbbb #bbbbbb #dddddd; padding-left:50px; } li{ width:65px; margin:5px; font-family:arial, sans-serif; font-size:10pt; text-indent:5px; } li:hover{ background-color:navy; color:white; } #b{ top:50px; left:10px; } </style> <script> function animate(opts) { clearInterval(opts.el.timer); var start = new Date; var delta = opts.delta || linear; var height = parseFloat(opts.el.style.height); opts.el.timer = setInterval(function() { var progress = (new Date - start) / opts.duration; if (progress > 1) progress = 1; opts.step( delta(progress),height ); if (progress == 1) { clearInterval(opts.el.timer); opts.complete && opts.complete(); } }, opts.delay || 20); } function elastic(progress) { return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress) } function linear(progress) { return progress } function quad(progress) { return Math.pow(progress, 2) } function quint(progress) { return Math.pow(progress, 5) } function makeEaseInOut(delta) { return function(progress) { if (progress < .5) return delta(2*progress) / 2 else return (2 - delta(2*(1-progress))) / 2 } } function makeEaseOut(delta) { return function(progress) { return 1 - delta(1 - progress) } } window.onload = function() { var input = document.getElementById("b"); var menu = document.getElementById("right_menu"); var body = document.body; var n = 0; input.onclick = function(){ n ^= 1; var to = n ? 0 : 125, display = n ? "none" : "block"; !n && (menu.style.display = display) animate({ el : menu, duration: 1000, delta: makeEaseInOut(linear), step: function(delta,height) { menu.style.height = delta*(to-height)+height+"px"; }, complete : function() {menu.style.display = display} }) }; body.onclick = function(event){ var event = event || window.event; var target = event.target || event.srcElement; if(target!=input && target!=menu &&!n && target.tagName != 'LI') input.onclick() } } </script> </head> <body> <input type='button' id='b' value = 'Click'> <ul id='right_menu' style="height: 125px"> <li>Effect 1</li> <li>Effect 2</li> <li>Effect 3</li> <li>Effect 4</li> </ul> </body> </html> |
Цитата:
Главное чтобы они кого-от заинтересовали... ;) |
Цитата:
Кстати, пусть оффтоп, но: уже неоднократно на форуме сталкиваюсь в разл. темах с Вашими комментариями - и всегда с удовольствием их читаю. Честно, Вы круты!) Насчёт задачи - кое-что таки наклепал сам: <!DOCTYPE html> <html> <head> <meta charset=utf-8> <title>JS Bin</title> <style> html, body{ height:100%; margin:0; padding:0; } #right_menu, li{ margin:0; padding:0; display:block; } #right_menu{ position:absolute; width:65px; height:125px; background-color:#cccccc; border:2px solid; border-color: #dddddd #bbbbbb #bbbbbb #dddddd; padding-left:50px; } li{ width:60px; height:25px; margin:5px; line-height:25px; font-family:arial, sans-serif; font-size:10pt; text-indent:5px; } li:hover{ background-color:navy; color:white; } #b{ position:absolute; left:10px; } </style> </head> <body> <ul id='right_menu'> <li></li> <li></li> <li></li> <li></li> </ul> <input type='button' id='b' value = 'Click'> <script> //запишем ссылку на объект-кнопку в перем-ую var button = document.getElementById('b'); //получим контейнер UL в перем-ую var menu=document.getElementById('right_menu'); //меню скрыто при загрузке стр-цы menu.style.display='none'; //расположим кнопку справа-вверху от меню (позиционируем меню) if(window.getComputedStyle){ menu.style.left=parseInt(getComputedStyle(button).left)+'px'; menu.style.top=parseInt(getComputedStyle(button).top)+'px'; }else{ //для IE8 menu.style.left=parseInt(button.currentStyle.left)+'px'; menu.style.top=parseInt(button.currentStyle.top)+'px'; } var flag = false; //ф-ция отображ-я меню function show(){ menu.style.display='block'; //при выезжании меню текста нет var lis = document.querySelectorAll('li'); for(var i=0; i<lis.length;i++){ lis[i].innerHTML = ''; } //ширина и высота меню var width = 0; var height = 0; return function frame_show() { // функция для отрисовки width++; height += 2; menu.style.width = width + 'px'; menu.style.height = height + 'px'; if (width == 65) { clearInterval(timer_show); // завершить анимацию //отразить текст в "гот." меню setTimeout(function(){ var lis = document.querySelectorAll('li'); lis[0].innerHTML = 'Effect 1'; lis[1].innerHTML = 'Effect 2'; lis[2].innerHTML = 'Effect 3'; lis[3].innerHTML = 'Effect 4'; },50); } } } //ф-ция сокрытия меню function hide(){ //при въезжании меню текста нет (чтоб не "маячил") var lis = document.querySelectorAll('li'); for(var i=0; i<lis.length;i++){ lis[i].innerHTML = ''; } if(window.getComputedStyle){ var width = parseInt(getComputedStyle(menu).width); var height = parseInt(getComputedStyle(menu).height); }else{ //для IE8 width = parseInt(menu.currentStyle.width); height = parseInt(menu.currentStyle.height); } return function frame_hide() { // функция для отрисовки width--; height -= 2; menu.style.width = width + 'px'; menu.style.height = height + 'px'; if (height == 0) { clearInterval(timer_hide); // завершить анимацию //тут же скрыть меню полностью setTimeout(function(){ menu.style.display='none'; },60); } } } //переключать режим видимости контейнера (кликом по кнопке) button.onclick=function(event){ if(flag == false){ timer_show = setInterval(show(),1); flag = true; }else{ timer_hide=setInterval(hide(),1); flag=false; } } //скрыть контейнер при наж-ии вне кнопки button.onblur=function(event){ timer_hide=setInterval(hide(),1); flag=false; } </script> </body> </html> |
Цитата:
Цитата:
|
Цитата:
Я новичок, поэтому не знаю: как Вы сделали здесь код запускаемым? |
Часовой пояс GMT +3, время: 12:30. |