Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Непонятное поведение скрипта (https://javascript.ru/forum/jquery/50859-neponyatnoe-povedenie-skripta.html)

eucalipt 14.10.2014 19:30

Непонятное поведение скрипта
 
Здравствуйте. С сегодняшнего дня я открыл для себя некоторые прелести Jquery, хотя раньше был яростным его противником. Оказалось намного удобнее.

У меня есть header (его id="header"), в этом хедере - 2 section. Левая - это лого сайта, а в правом содержатся 2 div'a, каждый из которых является кнопкой.

В чем суть проблемы: в теге body есть биъэйвиор onscroll, при котором включается функция changeHeader()
function changeHeader() {
	
	if ($(document).scrollTop() > 10) {
		
		$("#header").animate({ // Анимируем сам хедер
      lineHeight: "64px",
		 backgroundColor: "rgba(255, 255, 255, 1)"
    }, 100);
		
		$("div.logo span").animate({ // Анимируем Logo
      color: "rgba(39, 135, 164, 1)"
    }, 100);
		
		$("#header section div.sign").animate({ // Анимируем sign up
			borderColor: "#cccccc",
			color: "#999999"
    }, 100);
		
	} else {
		
		$("#header").animate({ // Анимируем сам хедер
      lineHeight: "100px",
		 backgroundColor: "rgba(255, 255, 255, 0)"
    }, 100);
		
	}
}


Как вы можете видеть из кода, при прокрутке страницы больше чем на 10, происходят некоторые изменения в стилизации элементов. Но почему-то если долго крутить страницу вниз, то изменения именно только (!) кнопок Sign Up и Sign In происходят только после окончания прокрутки. Остальные элементы меняют стиль сразу после того, как значение прокрутки становится больше 10.

А когда же мы крутим страницу вверх, и когда выполняется условие else, то есть когда значение прокрутки становится меньше 10, то, пока мы все еще кротим колесико, изменение стиля #header не происходит опять же до полной остановки прокрутки колесика.

Если при прокрутке вниз пользоваться скроллбаром, то изменения кнопок авторизации не вступят в силу, пока я не отпущу скроллбар.

Как решить эту проблему?

eucalipt 14.10.2014 20:07

Хотелось бы запустить ВСК эти анимации одновременно, что бы все сработали одновременно, сразу же после того, как значение прокрутки стало больше 10.

danik.js 14.10.2014 20:36

Цитата:

Сообщение от eucalipt
открыл для себя некоторые прелести Jquery

Поздно открыл. Щас это делается тупо сменой css-класса, на что jQuery нафиг не сдалась, а анимация уже в css (css3 transitions)

eucalipt 14.10.2014 20:41

Но ведь вам известно решение
 
Но ведь вы знаете, как исправить проблему?

danik.js 14.10.2014 20:45

<!DOCTYPE html><style>
.header{
    height: 80px;
    background: red;
    transition: all 0.3s;
    position: fixed;
    left: 0;
    right: 0;
}
.header.compact{
    height: 40px;
    background: blue;
}
</style>
<header class="header" id="header">

</header>

<main style="height:800px"></main>

<script>
    var header = document.getElementById('header');
    var scrolled = false;
    window.onscroll = function(e) {
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        if (scrollTop > 10) {
            if (!scrolled) {
                header.className += ' compact';
                scrolled = true;
            }
        } else {
            if (scrolled) {
                header.className = header.className.replace('compact', '');
                scrolled = false;
            }
        }
    };
</script>

danik.js 14.10.2014 20:46

Флаг scrolled добавлен для исключения лишних обращений к DOM. Это важно в обработчике onscroll. И не важно юзаешь ты jQuery или нет. Даже наоборот - с привычным бестолковым стилем кода под jQuery это втройне важно.

danik.js 14.10.2014 20:47

Цитата:

Сообщение от eucalipt
Но ведь вы знаете, как исправить проблему?

Нет, я анимации jquery уже забыл.

eucalipt 14.10.2014 20:49

И, кстати, этого так просто не сделаешь, я уверен, что вы даже до конца тему не дочитали. У меня изменения должны происходить только при определенных значениях прокрутки, что на чистом CSS3 не сделаешь. Это вам не просто :hover, не так-то все просто здесь.

eucalipt 14.10.2014 20:51

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

danik.js 14.10.2014 20:55

eucalipt, смотри пример, жми кнопку Посмотреть. Как видишь там js-код. Никто и не говорил что без него можно обойтись.

eucalipt 14.10.2014 21:25

Я правильно понимаю работу предоставленного скрипта? Поправьте меня в случае чего, пожалуйста.
Описывал в комментариях.

var header = document.getElementById('header'); // Получаем id элемента и записываем его в переменную header
    var scrolled = false; // Как Вы писали, это флаг, он помогает снизить нагрузку на DOM страницы
    window.onscroll = function(e) { // Тут мы определяем, прокручивается ли окно (Альтернатива body onscroll=('..')?) и если
    // прокручивается, то запускаем анонимную функцию с параметром 'e'
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; // Переменная получает значение прокрутки
        if (scrollTop > 10) { // Если значение прокрутки больше 10
            if (!scrolled) { // И если страница не прокручивается (?)
                header.className += ' compact'; // То к названию класса элемента с id header прикручиваем compact
                scrolled = true; // Тут непонятно (*)
            }
        } else { // Если мы вернулись в начало страницы
            if (scrolled) { // Если страница прокручивается (почему тут прокручивается, а там не прокручивается?)
                header.className = header.className.replace('compact', ''); // Удаляем compact из названия класса
                scrolled = false; // И тут непонятно (*2)
            }
        }
    }; // И, как я понимаю, все анимация происходит при помощи css?

danik.js 14.10.2014 22:40

Цитата:

Сообщение от eucalipt
Альтернатива body onscroll

Честно говоря, не знаю на че правильно вешать - на body или window. В хроме событие всплывает с элемента document.

Цитата:

Сообщение от eucalipt
с параметром 'e'

Ну он нам не понадобился, можно его и не указывать.
Цитата:

Сообщение от eucalipt
И если страница не прокручивается (?)

Наверно неудачное имя флага придумал. Смысл его: "скролл страницы больше 10 пикселей обработан". Или "шапку уже уменьшили".

шапка уменьшена = ложь
..
если (скролл > 10) {
    если (это неправда, что шапка уменьшена) {
      уменьшаем шапку;
      шапка уменьшена = правда
  }
} иначе {
    если (шапка уменьшена) {
        возвращаем шапку;
        шапка уменьшена = ложь
    }
}

Таким образом, мы не пытаемся уменьшить шапку если она уже уменьшена. А в твоем скрипте такой косяк есть.

Цитата:

Сообщение от eucalipt
И, как я понимаю, все анимация происходит при помощи css?

Да. Все современные браузеры, IE10+, аппаратное ускорение в большинстве случаев (правда не в случае height/width, насколько я знаю).
Чтоб увеличить охват старых браузеров, css3 свойства нужно продублировать с вендорными префиксами (-webkit, -moz и тд)

eucalipt 14.10.2014 22:54

Вот он, вот он профессионал. Объяснил про флаг так четко, что я сам кому хочешь теперь объясню. Если бы можно было апнуть карму 10 раз, апнул бы 11.

Но а если насчет решения, то я их совместил :D
$(function changeHeader() {
	var header = document.getElementById('header');
	var scrolled = false;
	
	window.onscroll = function(e) {
		
		if ($(document).scrollTop() > 10) {
		
			if (!scrolled) {
			
				$("#header").animate({ // Меняем Header
					lineHeight: "64px",
					backgroundColor: "#ffffff"
				}, {"duration":100, "queue":false});
				
				$("#header section div.logo span").animate({ // Меняем Logo
					color: "#CD0000"
				}, {"duration":100, "queue":false});
				
				$("#header section div.sign").animate({ // Меняем Sign Up и Sign In
					color: "#999999",
					borderColor: "#2787a4"
				}, {"duration":100, "queue":false});
				
				scrolled = true;
				
			}
			
		} else {
			
			if (scrolled) {
			
				$("#header").animate({ // Меняем Header
					lineHeight: "100px",
					backgroundColor: "rgba(255, 255, 255, 0)",
				}, {"duration":100, "queue":false});
				
				$("#header section div.logo span").animate({ // Меняем Logo
					
					color: "#ffffff"
				}, {"duration":100, "queue":false});
				
				$("#header section div.sign").animate({ // Меняем Sign Up и Sign In
					color: "#999999",
					borderColor: "#cccccc"
				}, {"duration":100, "queue":false});
				
				scrolled = false;
				
			}
			
		}
		
	}
});

eucalipt 14.10.2014 22:55

Еще раз огромное спасибо! Настоящий профессионал!

danik.js 14.10.2014 23:00

Цитата:

Сообщение от eucalipt
я их совместил

Лучше бы не совмещал :no:
window.onscroll - это (обязательно)
document.getElementById('header') - и это (оно у я и не юзается)
вернуть на функции jQuery.

Так а че, не устраивает что в убогом IE8-9 не будет анимации? Уж не знаю что лучше - дерганная тормозная анимация или резкая, но без лагов, смена.

eucalipt 14.10.2014 23:10

Да, строчку с header'ом просто убрать забыл.

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


Часовой пояс GMT +3, время: 16:03.