Jump to content
  • 0

Меню, плавно меняющее фон своих пунктов.


psywalker
 Share

Question

Всем добрый день!

Вот смастерил значит я меню с плавно меняющимся фоном на каждом пункте. Взял пример с этого сайта http://4m.net.ua/, но сделал своими силами, ради тренировки. Ну и как ожидалось, всё работает криво.

Проблема:

Если наводить на пункты медленно и так же медленно уводить с них мышь, то фон у пунктов плавно появляется и так-же плавно гаснет. Т.е. происходит так, как я и хотел.

А вот когда например быстро водишь по меню мышкой и сразу допустим нажимаешь несколько пунктов, то происходит какая та ерунда, а точнее пункты то гаснут, то нет, то половина вообще мигает. Короче сразу видно - некачественный подход к делу. Хотя я перестраховался, сделал всё через замыкание, потом использовал массивы для каждого вызова сетИнтервала, короче вроде делал танк, а получилась муха какая-та.

Вопрос:

Почему так происходит, что я сделал не так и как это починить?

http://psywalker.ru/Forum/JS/Primitive/Dom...-Plavnoe/2.html

Link to comment
Share on other sites

Recommended Posts

  • 0

Какая проблема с данной реализацией? Два совершенно независимых стека для анимации подсветки и затухания.

Возьмем, например, пять шагов подсветки, и установим там какое-то значение opacity

0 > .25 > .50 > .75 > 1

Что нам нужно сделать, когда пользователь не дождался конца анимации и решил убрать курсор?

Например, это произошло на 3м шаге, впереди еще два значения.

.50 > .75 > 1

Мы должны пойти в обратном направлении и начать анимацию затухания

.50 > .25 > 0

Итак, мы можем предкалькулировать некие значения опасити и записать их в массив

opacity_vals = [ 0, 0.25, 0.5, 0.75, 1 ]

Потом взять одну функцию, которая запущена циклически через timeout, и которой передавать направление движения, например 1 или -1

Брать текущую позицию, например 0, прибавлять вектор (1 или -1), смотреть, если новое значение меньше 0 или больше длинны массива opacity_vals, то ничего не делать, иначе присваивать текущую позицию равной самой себе плюс вектор.

Вектор присваивается при наведении (1) или при уводе (-1) мыши с объекта.

Link to comment
Share on other sites

  • 0
Потом взять одну функцию, которая запущена циклически через timeout, и которой передавать направление движения, например 1 или -1

Брать текущую позицию, например 0, прибавлять вектор (1 или -1), смотреть, если новое значение меньше 0 или больше длинны массива opacity_vals, то ничего не делать, иначе присваивать текущую позицию равной самой себе плюс вектор.

Вектор присваивается при наведении (1) или при уводе (-1) мыши с объекта.

Извини плиз, а вот эту часть не понял блиин ;)

Link to comment
Share on other sites

  • 0
Извини плиз, а вот эту часть не понял блиин ;)

У тебя есть нода. Она будет выступать объектом анимации. Для анимации нам нужно

1. Массив значений прозрачностей

2. Направление движения (вектор), который будет равен 1, если мы подсвечиваем элемент, и -1, если убираем прозрачность.

3. Некая функция, которая зациклена сама на себя, которая будет выполнять некоторое действие. Зацикливание делается через таймаут

4. Есть два события: активация и затухание.

	<div id="me" style="background: #fc2">hover me</div>
<script type="text/javascript">
var node = document.getElementById( "me" );
var animator = node._animator = {}; // создаем свойство ноды
animator.node = node; // замыкаем объект и ноду
animator.opacities = [ 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ]; // наш массив значений
animator.vector = 0; // направление движения, по умолчанию 0
animator.index = 9; // текущий индекс в нашем массиве, равен 9, т.е. opacity = 1
animator.loop = function ( ) {
var self = this;
setTimeout( function(){ self.loop() }, 13 ); // запускаем саму себя через время

var newIndex = this.index + this.vector; // смотрим, какой новый индекс

if ( newIndex < 0 || newIndex >= this.opacities.length || this.vector == 0 ) return; // если новый индекс за пределами значений или вектор равен 0, то выходим
this.index = newIndex; // присваиваем новый индекс
this.node.style.opacity = this.opacities[ newIndex ]; // устанавливаем новую прозрачность

};
animator.loop();

node.onmouseover = function( ) { this._animator.vector = -1 }; // при наведении и уводе мыши меняем вектор
node.onmouseout = function( ) { this._animator.vector = 1 };
</script>

Link to comment
Share on other sites

  • 0
setTimeout( function(){ self.loop() }, 13 );

Ща модно так писать:

setTimeout(arguments.callee, 13 );

deprecated фичами не пользуюсь. ;)

1) Не пойму, если у меня будет несколько пунктов, то как одна переменная var animator может хранить ссылки на все пункты?

Для того, чтобы это работало для множества элементов, лучше сделать некий синглтон, который бы нужной ноде приделывал бы анимацию.

Например

var fade = function( node ){

// do something here

}

И потом делать fade( "me" );

Link to comment
Share on other sites

  • 0

В общем я тут накидал вариант, вроде работает, но как именно, мне вообще непонятно((( Как же это для меня сложно, ппц просто.

Но я буду ещё разбираться, но боюсь, что шансов у меня мало.

http://psywalker.ru/Forum/JS/Primitive/Dom...-Plavnoe/3.html

Link to comment
Share on other sites

  • 0

http://psywalker.ru/Forum/JS/Primitive/Dom...-Plavnoe/3.html

Давай начнём прям сначала:

1) for(var i=0;i<aLink.length;i++){

Этим циклом проходимся по всем ссылкам.

2) var div = aLink.parentNode.getElementsByTagName('div');

Вот тут значит мы создали массив дивов в родителе нашей ссылки

3) var animator = node._animator = {};

Вот это действие мне вообще непонятно

4) animator.node = node;

Вот тут свойство у нашего объекта .node получает ссылку на нашу ноду

5) animator.vector = 0;

animator.index = 0;

animator.opacities = [ 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ];

Тут всё ясно. Прописываем свойства.

6) animator.loop = function ( ) {

var self = this;

setTimeout( function(){ self.loop() }, 15 );

var newIndex = this.index + this.vector;

if ( newIndex < 0 || newIndex >= this.opacities.length || this.vector == 0 ) return;

this.index = newIndex;

this.node.style.opacity = this.opacities[ newIndex ];

};

animator.loop();

Вот тут непонятно, функция эта вызывается и работает постоянно?

7) (function(node){

aLink.onmouseover = function(){

node._animator.vector = 1;

}

aLink.onmouseout = function( ) { node._animator.vector = -1 }

})(node)

Вот тут с помощью замыкания мы сохранили видимо в замыкании сохранили ссылку на нашу ноду и благодаря этому при наведении и уведении мыши функция берёт это значение из своего замыкания. Без этого не работало.

Вопрос:

Как это всё работает и почему?

Link to comment
Share on other sites

  • 0
3) var animator = node._animator = {};

Вот это действие мне вообще непонятно

Мы создали локальную (в нашем случае, все же глобальную) переменную animator, но вдобавок еще и свойство у ноды _animator

Это сделано для облегчения использования переменной в дальнейшем, нам теперь просто можно присваивать свойства объекту animator, что немедленно отразится на свойствах объекта node._animator, потому что они ссылаются на один и тот же объект.

4) animator.node = node;

Вот тут свойство у нашего объекта .node получает ссылку на нашу ноду

Объект animator присвоен ноде, но он не знает, какой именно ноде он присвоен. Чтобы знал, замыкаем одно на второе.

Вот тут непонятно, функция эта вызывается и работает постоянно?

Да.

Вот тут с помощью замыкания мы сохранили видимо в замыкании сохранили ссылку на нашу ноду и благодаря этому при наведении и уведении мыши функция берёт это значение из своего замыкания. Без этого не работало.

Ты там намудрил прилично. В моем коде не нужны замыкания.

Как это всё работает и почему?

Фаербаг в зубы и вперед!

Link to comment
Share on other sites

  • 0
4) animator.node = node;

Вот тут свойство у нашего объекта .node получает ссылку на нашу ноду

Объект animator присвоен ноде, но он не знает, какой именно ноде он присвоен. Чтобы знал, замыкаем одно на второе.

Разве тут не наоборот? Нода присвоена как свойство объекта аниматор?

И что значит замыкаем одно на второе?

Ты там намудрил прилично. В моем коде не нужны замыкания.

А дело в том, что мне же нужно, чтобы именно у дивов фон исчезал и появлялся, а не у ссылок, поэтому я и использовал замыкание.

Фаербаг в зубы и вперед!

Да это понятно, я конеш буду пробовать

Link to comment
Share on other sites

  • 0

s0rr0w

Вот сделал почти, кое что упростил, но почему то не работает. Объясни плиз, почему.

Вот код:

self.index+=self.vector;
if(self.index<0||self.index>self.opacitys.length || self.vector==0 ){return;}
self.node.style.opacity = self.opacitys[self.index];

Ведь когда мы наводим мышь на пункт и вектор становится равным 1, а значит вот эта запись будет прибавлять к self.index +=self.vector; , а разве нет?

Тогда почему не работает?

http://psywalker.ru/Forum/JS/Primitive/Dom...-Plavnoe/4.html

Я просто не пойму, чем верхняя запись хуже этой?

var newIndex = self.index+self.vector

if(newIndex<0||newIndex>=self.opacitys.length){return;}
self.index = newIndex;
//alert(self.vector)
self.node.style.opacity = self.opacitys[newIndex];

Link to comment
Share on other sites

  • 0
Разве тут не наоборот? Нода присвоена как свойство объекта аниматор?

И что значит замыкаем одно на второе?

Телефон лежит в коробке. Коробку погрузили на корабль. Телефон знает, что он на корабле? Нет, потому что его мир - коробка. А вот уже коробка знает, что она в корабле. Нужно проделать в коробке "дырочку", чтобы телефон знал, где находится его коробка.

А дело в том, что мне же нужно, чтобы именно у дивов фон исчезал и появлялся, а не у ссылок, поэтому я и использовал замыкание.

Анимация вешается на див. На ссылку вешается активация анимации у дива. Лампочка на потолке, а выключатель на стене. Значит ли это то, что раз выключатель на стене, то он не сможет включить лампочку на потолке? Нет, есть провода, которые это позволяют. Так и тут. То, что ссылка и див два разных элемента, это еще не значит, что ты не сможешь при клике на ссылку найти нужный див и изменить свойство объекта _animator.

s0rr0w

Вот сделал почти, кое что упростил, но почему то не работает. Объясни плиз, почему.

Вот код:

self.index+=self.vector;
if(self.index<0||self.index>self.opacitys.length || self.vector==0 ){return;}
self.node.style.opacity = self.opacitys[self.index];

Ведь когда мы наводим мышь на пункт и вектор становится равным 1, а значит вот эта запись будет прибавлять к self.index +=self.vector; , а разве нет?

Тогда почему не работает?

Не работает потому, что ты постоянно изменяешь значение индекса, и его значения спокойно себе выходят за пределы [0..длинна массива]

Что будет после того, как ты достиг конца массива? Чему будет равен index?

Link to comment
Share on other sites

  • 0
То, что ссылка и див два разных элемента, это еще не значит, что ты не сможешь при клике на ссылку найти нужный див и изменить свойство объекта _animator.

А как правильно это сделать, если внутри .onmouseover = function(){ уже не видно никаких дивов?

Не работает потому, что ты постоянно изменяешь значение индекса, и его значения спокойно себе выходят за пределы [0..длинна массива]

Ну правильно делаю, что изменяю, а если значение выходит за пределы, то мы выходим из функции ретурном, да и всё. Где тут подвох?

Что будет после того, как ты достиг конца массива? Чему будет равен index?

index будет равен 10, далее мы снова выходим ретурном из функции, а что в этом плохого?

Link to comment
Share on other sites

  • 0
А как правильно это сделать, если внутри .onmouseover = function(){ уже не видно никаких дивов?

Видно. Сделай alert( this )

Ну правильно делаю, что изменяю, а если значение выходит за пределы, то мы выходим из функции ретурном, да и всё. Где тут подвох?

Фаербаг :lol:

index будет равен 10, далее мы снова выходим ретурном из функции, а что в этом плохого?

Возьми фаербаг, напиши в коде

self.index+=self.vector;

console.debug( self.index );

запусти скрипт, открой консоль фаербага и посмотри, что ты там увидишь.

Link to comment
Share on other sites

  • 0
Видно. Сделай alert( this )

Вообще почему то показывает адрес страницы :lol:

Ну правильно делаю, что изменяю, а если значение выходит за пределы, то мы выходим из функции ретурном, да и всё. Где тут подвох?

Фаербаг smile.gif

Ну вроде посмотрел, и всё равно не пойму, в чём подвох?

Возьми фаербаг, напиши в коде

self.index+=self.vector;

console.debug( self.index );

запусти скрипт, открой консоль фаербага и посмотри, что ты там увидишь.

По началу видел нули, а другие не могу так почему-то увидеть.

Link to comment
Share on other sites

  • 0
Вообще почему то показывает адрес страницы :lol:

Это нормально, это так ссылки показываются.

По началу видел нули, а другие не могу так почему-то увидеть.

У тебя изменение индекса идет постоянно, независимо от того, больше стал он или меньше.

Link to comment
Share on other sites

  • 0
Это нормально, это так ссылки показываются.

Ну вот именно, показываются значит ссылки, а не дивы.

По началу видел нули, а другие не могу так почему-то увидеть.

У тебя изменение индекса идет постоянно, независимо от того, больше стал он или меньше.

Но как же так, я же ведь if-ом проверяю и если что, то ретурном выхожу ведь?

Link to comment
Share on other sites

  • 0
Ну вот именно, показываются значит ссылки, а не дивы.

А зная ссылку, типа трудно найти нужный див?

Но как же так, я же ведь if-ом проверяю и если что, то ретурном выхожу ведь?

До того как присвоил, или после?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy