На сайте Apple (блок "Самый мощный iMac в истории") есть эффект параллакса. При прокрутке до определенной точки картинка начинает прокручиваться медленнее текста, и в конце медленная прокрутка сменяется стандартной. Как можно реализовать такой же эффект?
UPD:
Есть скрипт, который при прокрутке до определенной высоты замедляет прокрутку блока. Сначала у нас блок с абсолютным позиционированием, при прокрутке определенного количества пикселей блок получает фиксированное позиционирование и начинает прокручиваться медленнее основного контента.
// Наш элемент, который будет замедляться
var $element = $('.first'),
/*
* Последняя позиция скролла, нужна
* для вычисления
*/
lastScrollTop = 0,
/*
* Отступ сверху для нашего блока
* с фиксированным и абсолютным
* позиционированием
*/
defaultElementAbsoluteTop = 150,
defaultElementFixedTop = 90,
// Коэффициэнт замедления
n = 4;
// Отслеживаем скролл страницы
$(window).scroll(function (event) {
// Вычисляем текущее положение
var scrollTop = $(window).scrollTop(),
/*
* Вычисляем положение нашего блока
* от верхней части сайта/родителя.
* Т.к. этот элемент до этого был абсолютным,
* то у него отступ сверху всегда одинаков,
* А когда подходит момент, когда нужно его фиксировать
* отступ расчитывается от последнего, который был
* 150 пикселей. Это неправильно. Я ввел проверку,
* Если отступ стандартный абсолютный равен
* текущему, то, при фиксировании блока
* ставим ему оступ фиксированного блока
* и отсюда начинаются правильные расчеты
*/
elementTop = $element.position().top == defaultElementAbsoluteTop ? defaultElementFixedTop : $element.position().top;
if(scrollTop < 60)
{
/*
* Проскролили меньше, чем на 60 пикселей
* То оставляем абсолютное позиционирование
*/
$element.removeClass('fixed');
// И ставим элементу абсолютный отступ сверху
$element.css({
top: defaultElementAbsoluteTop
});
}
else
{
// Фиксируем элемент
$element.addClass('fixed');
// TODO: удалить!
//return;
/*
* Если прошлое положение меньше,
* чем текущее, значит двигаемся <вниз>
*/
if (scrollTop > lastScrollTop){
// Вычисляем разницу перемещения
var diff = scrollTop - lastScrollTop;
// Даем отступ сверху в n раз меньше, чем скролл
$element.css({
top: elementTop - diff/n + 'px'
});
// В противном случае, двигаемся <вверх>
} else {
// Вычисляем разницу перемещения
var diff = lastScrollTop - scrollTop;
/*
* Вычисляем результирующее положение нашего элемента,
* с учетом замедления n
*/
resultElementTop = elementTop + diff/n;
/*
* Если конечный результат вышел больше,
* чем отступ сверху по умолчанию,
* то даем стандартный отступ.
* Иначе даем результирующий отступ
*/
resultElementTop = resultElementTop > defaultElementFixedTop ? defaultElementFixedTop : resultElementTop;
// Позиционируем элемент
$element.css({
top: resultElementTop + 'px'
});
}
}
// Запоминаем последнюю позицию скролла
lastScrollTop = scrollTop;
});
Нужно, чтобы блок сначала был с position: absolute, при прокрутке до определенного участка блок получает position:fixed и прокручиваетс медленнее. При прокрутке страницы ещё ниже, блок опять становится абсолютно спизиционированным. При рокрутке обратно вверх блок получает фиксированное позиционирование и прокручивается вниз с того момента, на котором остановился при прокрутке вверх.
Ответ
Поковырялся, вот что получилось.
firstPosScroll = []; // позиция курсора, с которой объект видим
windowH = $(window).height(); // высота окна
getPosScroll(); // заполнение вышеуказанных позиций
$(window).resize(function() { // при изменении размера окна пересчитываем позиции
getPosScroll();
})
$(window).scroll(function() { //обработчик скролла
posScroll = $(this).scrollTop(); // текущая позиция курсора
posMiddle = windowH / 2; // середина окна
$('.prlx').each(function(i, v) { // для каждого объекта
offsetObj = $(this).offset().top; // положение объекта относительно верха документа
posObj = offsetObj - posScroll; // текущая позиция объекта
koef = 1 - ($(this).find('.logo').height() / $(this).find('.desc').height()); // коэффициент замедления обратно пропорционален разнице высот картинки и описания
if (posObj < posMiddle && posObj + $(this).height() > posMiddle) { //условие видимости объекта
$(this).find('.logo').css({
'top': (posScroll - firstPosScroll[i] - posMiddle) * koef + 'px'
}); // задаем высоту
}
});
});
function getPosScroll() {
$('.prlx').each(function(i, v) {
firstPosScroll[i] = $(this).offset().top - windowH < 0 ? 0 : $(this).offset().top - windowH;
});
}
section {position: relative;}
section.left-logo>div.logo {left: 0;}
section.left-logo>div.desc {float: right;width: 50%;}
section.right-logo>div.logo {right: 0;}
div.logo {position: absolute;width: 50%;}
section.right-logo>div.desc {float: left;width: 50%;}
header {height: 800px;background: #e6e6e6;}
img {max-width: 100%;}
div.p {margin: 20px 0;}
div.clear {clear: both;width: 100%;}
Комментариев нет:
Отправить комментарий