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
  Quote
Потом взять одну функцию, которая запущена циклически через timeout, и которой передавать направление движения, например 1 или -1

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

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

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

Link to comment
Share on other sites

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

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

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
  Great Rash said:
setTimeout( function(){ self.loop() }, 13 );

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

setTimeout(arguments.callee, 13 );

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

  psywalker said:
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
  psywalker said:
3) var animator = node._animator = {};

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

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

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

  psywalker said:
4) animator.node = node;

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

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

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

Да.

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

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

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

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

Link to comment
Share on other sites

  • 0
  Quote
4) animator.node = node;

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

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

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

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

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

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

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

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

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
  psywalker said:
Разве тут не наоборот? Нода присвоена как свойство объекта аниматор?

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

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

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

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

  psywalker said:
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
  Quote
То, что ссылка и див два разных элемента, это еще не значит, что ты не сможешь при клике на ссылку найти нужный див и изменить свойство объекта _animator.

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

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

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

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

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

Link to comment
Share on other sites

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

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

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

Фаербаг :lol:

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

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

self.index+=self.vector;

console.debug( self.index );

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

Link to comment
Share on other sites

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

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

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

Фаербаг smile.gif

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

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

self.index+=self.vector;

console.debug( self.index );

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

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

Link to comment
Share on other sites

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

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

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

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

Link to comment
Share on other sites

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

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

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

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

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

Link to comment
Share on other sites

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

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

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

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

Link to comment
Share on other sites

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

Т.е. изначально присвоить ей свойство, которое ссылается на нужный див?

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

До.

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

  • Обсуждения

    • Актуальные контакты: Telegram: @Nikker_web E-Mail:   tarasevich.email@gmail.com Портфолио https://www.behance.net/d4d4186e Разрабатываю дизайн групп в соц сетях, сайтов, приложений, другой дизайн под заказ    
    • Актуальные контакты: Telegram: @Nikker_web E-Mail:   tarasevich.email@gmail.com   Разрабатываю дизайн групп в соц сетях, сайтов, приложений, другой дизайн под заказ   Портфолио https://www.behance.net/d4d4186e
    • Доброго всем времени суток. Прошу помощи. Научите принципу изменения футера. Движок Xenforo. Версия 2.2.10. Стиль дефолтный. Что именно нужно в итоге на фото примере. Мой шаблон app.footer less имеет следующее значение.  .p-footer { .xf-publicFooter(); a { .xf-publicFooterLink(); } } .p-footer-inner { .m-pageWidth(); .m-pageInset(); padding-top: @xf-paddingMedium; padding-bottom: @xf-paddingLarge; } .p-footer-row { .m-clearFix(); margin-bottom: -@xf-paddingLarge; } .p-footer-row-main { float: left; margin-bottom: @xf-paddingLarge; } .p-footer-row-opposite { float: right; margin-bottom: @xf-paddingLarge; } .p-footer-linkList { .m-listPlain(); .m-clearFix(); > li { float: left; margin-right: .5em; &:last-child { margin-right: 0; } a { padding: 2px 4px; border-radius: @xf-borderRadiusSmall; &:hover { text-decoration: none; background-color: fade(@xf-publicFooterLink--color, 10%); } } } } .p-footer-rssLink { > span { position: relative; top: -1px; display: inline-block; width: 1.44em; height: 1.44em; line-height: 1.44em; text-align: center; font-size: .8em; background-color: #4682B4; border-radius: 2px; } .fa-rss { color: white; } } .p-footer-copyright { margin-top: @xf-elementSpacer; text-align: center; font-size: @xf-fontSizeSmallest; } .p-footer-debug { margin-top: @xf-paddingLarge; text-align: right; font-size: @xf-fontSizeSmallest; .pairs > dt { color: inherit; } } @media (max-width: @xf-responsiveMedium) { .p-footer-row-main, .p-footer-row-opposite { float: none; } .p-footer-copyright { text-align: left; padding: 0 4px; // aligns with other links } }  
    • Нужны сайты с примерами верстки, типа https://css-tricks.com/. Типовые приемы и нестандартные на все случаи жизни. Накидайте ссылок.
×
×
  • 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