02.02.2014, 03:34
|
Аспирант
|
|
Регистрация: 02.02.2014
Сообщений: 48
|
|
События / таймеры
Здравствуйте!
Задача: необходимо, чтобы при нажатии на кнопку меню плавно из-под неё выезжало. При повторном нажатии или нажатии НЕ на неё - так же плавно "въезжало" в неё. 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, 02.02.2014 в 16:14.
|
|
02.02.2014, 10:29
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,205
|
|
Сообщение от Boolean_Type
|
задание срочное. Поэтому даже не знаю, что тут можно сделать
|
Как вариант, предложить оплату, может кого-то это заинтересует...
|
|
02.02.2014, 10:51
|
Профессор
|
|
Регистрация: 23.10.2010
Сообщений: 2,718
|
|
|
|
02.02.2014, 15:47
|
Аспирант
|
|
Регистрация: 02.02.2014
Сообщений: 48
|
|
Сообщение от ksa
|
Как вариант, предложить оплату, может кого-то это заинтересует...
|
:-)))
Полностью согласен)))
Да только это не от заказчика, а на курсах задали.
|
|
02.02.2014, 15:50
|
Аспирант
|
|
Регистрация: 02.02.2014
Сообщений: 48
|
|
Спасибо большое, со св-вом CSS transition знаком, но нужно именно JS.
Мне кажется, мой алгоритм в общем верен, просто из-за нехватки теор. знаний я где-то лажаю...
|
|
02.02.2014, 18:01
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
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>
|
|
02.02.2014, 20:39
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,205
|
|
Сообщение от Boolean_Type
|
это не от заказчика, а на курсах задали.
|
Какая разница чьи деньги?
Главное чтобы они кого-от заинтересовали...
|
|
03.02.2014, 15:51
|
Аспирант
|
|
Регистрация: 02.02.2014
Сообщений: 48
|
|
Сообщение от рони
|
Вариант на основе темы
|
Рони, спасибо большое! В изучении пока не дошёл до анимации, поэтому пока не всё понятно в Вашем коде, но, как только дойду, обязательно подробно изучу каждую строку.
Кстати, пусть оффтоп, но: уже неоднократно на форуме сталкиваюсь в разл. темах с Вашими комментариями - и всегда с удовольствием их читаю. Честно, Вы круты!)
Насчёт задачи - кое-что таки наклепал сам:
<!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>
Последний раз редактировалось Boolean_Type, 03.02.2014 в 17:56.
|
|
03.02.2014, 16:21
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,105
|
|
Сообщение от Boolean_Type
|
При отладке выдаёт ошибку в строках 066,067
|
Цитата:
|
метод window.getComputedStyle ... Поддерживается всеми браузерами, кроме IE<9.
|
getComputedStyle и currentStyle
|
|
03.02.2014, 16:47
|
Аспирант
|
|
Регистрация: 02.02.2014
Сообщений: 48
|
|
Да-да, уже исправил код в предыд. сообщении, думал, успею до того, как Вы увидите.)) Спасибо)
Я новичок, поэтому не знаю: как Вы сделали здесь код запускаемым?
|
|
|
|