На сайте 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 и прокручиваетс медленнее. При прокрутке страницы
ещё ниже, блок опять становится абсолютно спизиционированным. При рокрутке обратно
вверх блок получает фиксированное позиционирование и прокручивается вниз с того момента,
на котором остановился при прокрутке вверх.
Ответы
Ответ 1
Поковырялся, вот что получилось.
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%;}
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque
consequatur dolore, mollitia quas quo reiciendis soluta! A beatae, temporibus? Amet
animi delectus hic illo quaerat quia quos ratione rerum tempora.
Ad asperiores aspernatur assumenda blanditiis consectetur cum
dignissimos dolores est facilis, fugiat hic impedit maiores minima modi molestias,
natus nobis numquam optio perspiciatis possimus rem rerum tempora, tempore voluptatibus
voluptatum!
Consectetur cumque exercitationem necessitatibus provident quidem,
reiciendis rem similique tempore voluptatem voluptates. Accusantium consectetur deleniti
dignissimos eius hic id natus perferendis, porro possimus reprehenderit similique suscipit
tempora temporibus unde veritatis.
Accusamus aperiam, asperiores at atque beatae consectetur deleniti,
dolor dolores dolorum eius excepturi exercitationem fugiat iste iure libero magni maxime
molestiae nam numquam optio quibusdam reiciendis sit sunt voluptates voluptatum.
A, alias commodi incidunt iure iusto magnam minima natus, nulla
odio perferendis porro veritatis. Aliquid, animi consectetur eius, exercitationem fuga
impedit iusto nobis provident quibusdam quidem quisquam, soluta sunt tempore.
Aliquam amet aspernatur consectetur consequuntur cum, fugiat harum
hic, minima modi molestiae officia quia soluta. Assumenda eius iste nulla voluptas!
Amet assumenda corporis, eaque earum illum inventore mollitia quo sit.
A consequatur corporis inventore, mollitia necessitatibus nihil
nobis porro quibusdam rem voluptas! Atque blanditiis dicta dolores doloribus et facilis
fugiat, harum, id laborum nam nostrum, numquam provident reiciendis unde vitae?
A accusantium amet aut, autem cum delectus deleniti, dolorem dolores
ea eius, eos ex explicabo id incidunt minus molestias nam non obcaecati officiis repellat
rerum similique sit suscipit veritatis voluptatibus?
Architecto cum eaque ipsa iste magnam reprehenderit sint voluptatibus.
Ab asperiores atque, consequatur deserunt eum facilis id iste natus nisi obcaecati
porro, praesentium quas quia rerum sit soluta unde vel?
Aperiam architecto deleniti distinctio dolor eaque eligendi est
exercitationem laborum, maiores minima quasi repudiandae. Alias blanditiis, ex illum
in iure magni omnis quam quibusdam quis repudiandae sint vero. Aut, voluptatibus!
Adipisci dolorum ducimus fuga harum ipsa laudantium magni maxime
molestias nemo obcaecati perspiciatis quaerat qui rerum, saepe sequi voluptates voluptatum.
Amet dolorem eum explicabo facilis harum inventore perferendis perspiciatis quae.
Accusamus ad, alias animi at beatae dolore doloremque excepturi
explicabo fugiat ipsum iste iure iusto magnam molestiae nesciunt, praesentium quia
ratione recusandae rem rerum sit tempore velit veritatis vitae voluptate!
Cumque facere quo quod! A expedita fugit inventore nostrum quis.
Accusantium alias consectetur ea eveniet, harum laudantium nam officiis porro quo rerum.
Expedita illo iste nihil porro reprehenderit similique sint.
Delectus dignissimos doloremque dolorum esse excepturi iste molestiae
nulla quis, tempore! Aliquam aliquid architecto corporis debitis dolorem eum excepturi
expedita fugiat minus modi nostrum, omnis praesentium quaerat quas, reprehenderit veniam.
Autem doloremque ea eveniet illum labore magnam, maxime molestias
nobis odio omnis quam, suscipit. Ab deserunt ea esse laborum neque perferendis, porro
possimus quis quos reprehenderit sequi suscipit velit vitae!
Delectus dignissimos doloribus maiores natus necessitatibus perspiciatis
quia suscipit totam voluptatibus! Aliquam corporis dicta eos fugit hic magnam nihil
numquam quam sunt voluptates? Amet beatae corporis, culpa quia quibusdam repudiandae?
A architecto commodi ducimus explicabo illum impedit laboriosam
magni nemo perferendis quisquam! A autem deleniti deserunt fuga illum iure iusto labore
necessitatibus numquam, optio perspiciatis ratione, reiciendis rerum saepe temporibus?
Aspernatur consequuntur delectus eaque eligendi eveniet harum
impedit incidunt nisi nulla, odio rem repellat rerum sequi soluta temporibus vitae
voluptatum? Facere minus quidem repellat temporibus unde. In saepe soluta vero.
Assumenda aut dolores eaque laborum laudantium nemo neque, placeat
quod sint vero? Amet eos fuga laboriosam optio perferendis quidem repudiandae rerum
saepe! Fuga ipsam nihil officia provident quos veritatis vitae!
A ab accusamus aliquid animi distinctio dolorum eius facere fugiat
ipsam libero magni mollitia obcaecati odio odit, quam, rem sed soluta ullam vitae voluptas!
Commodi cupiditate minima nesciunt possimus voluptatem.
Accusamus animi at atque, ea earum eligendi eos exercitationem
harum illum magnam mollitia nemo neque quae quasi sint suscipit totam! Ducimus libero
quidem quis repudiandae, saepe voluptatem? Ab, cum illo!
Eveniet hic neque nihil praesentium suscipit. Accusamus aperiam
architecto at blanditiis consectetur consequatur doloremque dolores eligendi est, ex
laboriosam mollitia nemo nobis nostrum, quaerat quia repudiandae rerum temporibus.
Debitis, non.
Accusamus blanditiis cum expedita in laudantium minus natus omnis
optio, provident, quam quibusdam reiciendis tempora voluptate. Aperiam assumenda optio
perspiciatis placeat similique tempora vero! Corporis reiciendis veritatis voluptas!
Dignissimos,
recusandae.
Cupiditate distinctio fugiat incidunt ipsa iusto pariatur quo
ratione veritatis. Adipisci amet architecto asperiores consectetur consequatur cupiditate
dolorem, ducimus eveniet harum impedit, ipsa provident quo rerum saepe sint sit voluptatibus.
Aliquid architecto, delectus hic numquam praesentium quibusdam
quos tempora temporibus? Aliquam aliquid animi aperiam at atque beatae commodi dolores
doloribus itaque iusto molestiae mollitia non quaerat quas sequi, tempore voluptates.
Aperiam commodi doloremque error eum excepturi libero nobis obcaecati
sint veniam voluptas. Amet aperiam autem commodi dolor eligendi, esse, expedita facere
molestiae pariatur quae quisquam ratione sapiente similique tempora voluptate.
A architecto, harum laboriosam magnam necessitatibus, non optio
possimus quas quasi reiciendis sit voluptate! Aperiam asperiores dolorem ducimus eveniet,
fugit neque ratione temporibus? Aperiam eligendi illum incidunt maxime, quis soluta!
Ab accusamus animi aspernatur consectetur dolor dolore eligendi
explicabo impedit laborum molestiae nemo, non odit, officiis, reprehenderit unde. Accusantium
commodi dolorum fuga, impedit inventore optio quos sed ullam veniam voluptas.
Aperiam aspernatur consectetur doloremque facere inventore, minima
mollitia nesciunt quidem quisquam voluptatum. Ab accusamus aliquid at, commodi delectus
deleniti dolore dolorum libero obcaecati pariatur qui ratione saepe sed temporibus unde.
Beatae commodi, consectetur culpa eaque eveniet explicabo incidunt
nulla ullam. Accusantium amet animi aspernatur atque aut blanditiis cupiditate, distinctio
dolore, eum illum mollitia nam nisi nostrum, possimus qui sapiente sint.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt,
dignissimos, maxime. Impedit incidunt neque provident quaerat ratione, saepe sequi
voluptates. Amet assumenda commodi ducimus et maiores numquam quod sit voluptates.
Ab aliquid, cupiditate dolorem et id incidunt officiis omnis!
Ad aperiam at consectetur, debitis deserunt dolor et ex explicabo minima natus odio
quam quasi quo, repellendus tempore tenetur voluptas, voluptates?
A adipisci animi aperiam asperiores assumenda atque, consequatur
eaque enim explicabo facilis in ipsa ipsum magni natus numquam obcaecati optio, quibusdam
quod repudiandae soluta tenetur velit vero! Aliquam sunt, voluptatem.
Amet asperiores cumque, dicta eaque eos et illo impedit laborum
nesciunt quis repellat tempora veritatis, voluptates voluptatibus, voluptatum. Dolorem
doloribus eaque eligendi eos minus nesciunt quibusdam ratione ut voluptatem. Reiciendis.
Adipisci, at deleniti excepturi laboriosam magni necessitatibus
pariatur qui recusandae rerum temporibus? Ab aperiam aut, consequatur corporis dolore
eius enim esse exercitationem impedit ipsam laborum magni perferendis quam reprehenderit
veniam.
Aliquam dolore facilis minus quas? Accusamus adipisci at consectetur
cum deleniti deserunt dignissimos et eveniet impedit incidunt iste itaque, iusto maxime
nemo nihil nulla perspiciatis, possimus sunt vel velit! Illum.
Aliquid aperiam ea eaque eveniet ex hic, reiciendis. Accusamus
alias aliquid ea excepturi fuga laborum, maxime minima officia quisquam quos rem sed
tempore, velit veritatis, voluptatem? A deserunt possimus sunt!
Aperiam autem distinctio eligendi est iste. Accusamus aliquid
excepturi illo officia quia reprehenderit veniam! Alias cupiditate dicta dolorum. Autem
debitis delectus eum inventore iure minima nam numquam omnis quo sint!
Accusamus amet atque autem dolor enim esse est harum illum incidunt
maxime necessitatibus officia quas reiciendis repellat sed tempore totam, ullam unde,
vel voluptatum. Ducimus earum nesciunt possimus quos repellendus.
Corporis dicta distinctio dolorem exercitationem, inventore labore
nisi placeat quasi saepe vel? Accusantium alias, debitis dolor ducimus in labore nisi
nobis obcaecati officiis pariatur quasi quis, quisquam repellat temporibus vel?
Atque autem, culpa eos illum necessitatibus odio quaerat quasi
quis temporibus ut veritatis voluptatum. Dignissimos eligendi laborum necessitatibus
perspiciatis? Aliquam amet dignissimos doloremque eos fugiat itaque numquam possimus
repellat veritatis.
Accusamus aliquam delectus deserunt dignissimos dolore eligendi
est impedit laborum libero modi natus non officia pariatur quos sapiente similique
ut, veniam vitae voluptas voluptates! Ad commodi excepturi numquam quasi similique!
Cumque distinctio dolorum eius fuga labore natus officia placeat
quibusdam veritatis? Accusantium dolore id maiores quam qui, sapiente. Commodi eveniet
fugiat maiores nam odio omnis placeat, quasi qui quidem voluptates!
Asperiores at beatae cupiditate dolore eius eveniet fugiat hic
magnam, maxime minima modi mollitia nostrum numquam odit praesentium provident quaerat
quia, quibusdam quis quos recusandae rem sit tempore, unde voluptatem.
Amet ex, exercitationem incidunt, ipsam libero necessitatibus
nesciunt placeat quis reprehenderit temporibus, tenetur totam veritatis? At commodi
cumque eaque eligendi enim fuga harum, nihil nobis praesentium qui quis sint totam.
Dignissimos est iusto molestiae molestias quaerat repellendus
reprehenderit saepe tempora tempore velit! Asperiores corporis eos id, incidunt minus
quisquam ratione recusandae sit tempora vero. Asperiores beatae doloremque quasi quo
voluptatibus.
Accusamus aliquam assumenda consequuntur, debitis deleniti dicta
eos illo, inventore itaque porro rem repellendus, voluptates. Amet dolores doloribus
illo magnam molestias! Aspernatur dolorum fuga, mollitia nihil perspiciatis repellat
sapiente soluta?
Aspernatur blanditiis consectetur corporis dicta incidunt itaque
magni modi molestiae, mollitia nihil perferendis possimus quaerat quia quibusdam quos,
repellendus similique ullam, voluptatum. Commodi facilis maxime, ratione sint sunt
velit vero?
A ad aspernatur atque cumque deserunt dicta doloremque doloribus
enim ex expedita explicabo, facilis fugit id iusto labore, libero magni minima necessitatibus
nostrum possimus quaerat quibusdam quos recusandae sapiente temporibus!
Accusamus aliquid assumenda beatae commodi consequatur consequuntur
cum, dicta eaque eius eos id illo in ipsa magni necessitatibus nisi obcaecati omnis
quia recusandae sapiente similique sint vel voluptates. Aspernatur, delectus.
Ответ 2
Мой вариант решения - пример здесь. Описание всего, что происходит, в принципе, есть
в коде ниже. Отчасти использовал идею со страницы Apple, но обошелся без translate3D.
Основной HTML:
Основной CSS:
.content {
position: relative;
}
.slow {
position: absolute;
top: 100px;
}
JS:
var $window = $(window);
var $parent = $('.content').eq(1);
var $slow = $('.slow');
// сохраняем первоначальную позицию блока по отношению к родителю (100px)
var initialTop = $slow.position().top;
// эффект замедления
// то, на сколько пикселей будет двигаться блок при position: fixed
var translate = 1;
// указываем расстояние в пикселях до/после родителя, чтобы знать
// когда добавлять/убирать position: fixed
// могут быть равны 0, тогда определяться будет по позиции родителя
var parentBefore = 300,
parentAfter = 100;
// последнее значение $window.scrollTop(), для определения направления скролла
var previousScrollTop = 0;
// направление по умолчанию - вниз
var direction = -1;
// временные переменные
var parentTop = null,
parentBot = null;
function onScroll() {
// узнаем в каком направлении мы сейчас скроллим
// "1" - вверх, "-1" - вниз
direction = previousScrollTop > $window.scrollTop() ? 1 : -1;
previousScrollTop = $window.scrollTop();
// вычисляем верхнюю и нижнюю границу того, когда нам нужно начинать эффект
// верхняя граница: когда топ родителя + запас "before" достигает топа окна
// нижняя граница: когда низ родителя + запас "after" появляется снизу
var borderTop = $parent.offset().top - parentBefore - $window.scrollTop();
var borderBot = borderTop + parentAfter + $parent.height();
// если мы внутри границ
if (borderBot > $window.height() && borderTop <= 0) {
// достаем текущее положение элемента относительно окна
var currentTop;
// если скролим вверх, то при первом переключении на position: fixed,
// восстанавливаем сохраненное значение (см. parentTop)
if ($slow.css('position') === 'absolute') {
currentTop = parentTop;
} else {
// иначе берем текущую фиксированную позицию
currentTop = parseInt($slow.css('top'), 10);
}
// вычисляем новое значение со сдвигом в зависимости от направления
var nextTop = currentTop + translate * direction;
// проверка для того, чтобы не вылезать за пределы стартовой позиции
if (nextTop < initialTop) {
nextTop = initialTop;
}
// когда впервые попадаем в границы, добавляем запас "before" к позиции
if (!parentTop) {
nextTop += parentBefore;
}
$slow.css('position', 'fixed');
$slow.css('top', nextTop);
$slow.css('bottom', 'auto');
// сохраняем позицию относительно окна сверху
parentTop = $slow.position().top;
// сохраняем позицию относительно окна снизу
parentBot = $window.height() - $slow.position().top - $slow.height();
// если вышли за границу снизу, цепляем блок к низу родителя
} else if (borderBot < $window.height()) {
$slow.css('position', 'absolute');
$slow.css('top', 'auto');
// устанавливаем позицию блока относительно родителя из сохраненного
// значения (см. parentBot), с вычетом запасов "before" и "after"
$slow.css('bottom', parentBot - parentAfter + parentBefore + 'px');
// если вышли за границу сверху, восстанавливаем все состояния
} else if (borderTop > 0) {
$slow.css('position', 'absolute');
$slow.css('top', initialTop);
$slow.css('bottom', 'auto');
parentTop = null;
parentBot = null;
}
}
$window.on('scroll', onScroll);
Замеченные недостатки:
нельзя замедлять перемещение фиксированного блока меньше чем на 1px (переменная translate)
позиция блока при скролле всегда рандомная, т.к. перемещение выполняется при каждом
событии scroll.
Правка: JSBin в Firefox не видел функцию onScroll, которая была объявлена под $window.on('scroll',
onScroll);. Также Firefox даже если у элемента стоит top:auto, возвращает числовое
значение для вызова $el.css('top'), а не строку auto.
Ответ 3
Вот мой вариант:
HTML:
CSS:
.about .parallax {
height: 400px;
overflow: hidden;
position: relative;
}
.about .parallax img {
width: 100%;
position: absolute;
}
JS:
function parallax()
{
var $block = $('.parallax');
var $window = $(window);
for (var i = 0; i<$block.length; i++) {
var $item = $($block[i]),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $item.offset().top,
elemBottom = elemTop + $item.height(),
img = $item.find('img'),
heightParallax = img.height() - $block.height();
if ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)) {
var show = docViewBottom - elemTop;
var par = heightParallax / ($window.height() + $block.height());
var top = par * show * -1;
if (top > 0) {
img.css('top', '0px');
} else if (heightParallax < top * -1) {
img.css('top', heightParallax + 'px');
} else {
img.css('top', top + 'px');
}
} else if (elemTop >= docViewBottom) {
img.css('top', '0px');
} else if (elemTop <= elemTop) {
img.css('top', heightParallax + 'px');
}
}
}
$(window).scroll(function() {
parallax();
}).resize(function() {
parallax();
});
Результат: Piggy refer