
От автора: эффекта параллакс-скроллинга можно добиться множеством способов, однако я считаю, что большая их часть лишь имитирует глубину изображения. Взглянув на скринсейвер с OS X, я понял, что CSS 3D позволяет по-настоящему сместить изображения на задний план по оси Z, создавая настоящую перспективу и параллакс-эффект во время прокрутки изображений вверх и вниз.
Код нашего урока всего лишь прототип, но я считаю, что он достаточно интересен, чтобы рассказать вам про него. Заодно взгляните на демо на CodePen.
Основы
Код начинается с одного элемента разметки, тега div:
|
1 2 |
<div id="parallax-container"> </div> |
Этот блок будет наполняться изображениями, которые загружаются через JavaScript. Первым делом необходимо прописать стили для блока DIV и изображений внутри него:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#parallax-container { background: #16161d; margin: 0; overflow: hidden; perspective: 1200px; height: 100vh; width: 100vw; transform-style: preserve-3d; } #parallax-container img { transform-origin: center; box-shadow: 0 0 12px 12px rgba(0, 0, 0, 0.4); position: relative; } |
Прокрутка изображений
По методу прогрессивного улучшения необходимо вставить изображения в разметку, написать CSS код к ним и только потом с помощью JS прятать и управлять ими. Так как это всего лишь демо, я выбрал самый прямой маршрут. Имена наших изображений созданы по одному шаблону (wave1.jpg, wave2.jpg… и т.д.), т.е. я могу при помощи JS генерировать имена изображений. Я буду использовать скрипт ниже наряду с другими глобальными переменными:
|
1 2 3 4 5 6 7 8 9 |
var container = document.getElementById("parallax-container"), waveSrc = [], waves = [], imgLoc = "", j = 0; for (var i = 0; i < 10; i++) { waveSrc[i] = imgLoc+"wave"+(i+1)+".jpg"; } |
Мне понадобятся несколько случайных чисел, которые я буду генерировать в функции:
|
1 2 3 |
function getRandomInRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } |
Также мне нужны ссылки загружаемых изображений и текущая ширина и высота экрана (с условием, что браузер открыт на весь экран).
|
1 2 |
var screenWidth = window.screen.width, screenHeight = window.screen.height; |
После загрузки изображений и последовательной вставки в контейнер им задаются свойства .xPlane, .yPlane и zPlane с произвольными значениями. Данные свойства отвечают за позиционирование элементов в 3D пространстве. Мы оставили пустыми атрибуты alt в демо.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function preloadImage(filename){ var img=new Image(); img.onload = function(){ img.xPlane = getRandomInRange(-500, screenWidth - 500); img.yPlane = getRandomInRange(500, 1000); img.zPlane = getRandomInRange(300,2000); img.style = "transform: translate3d(" + img.xPlane +"px, " + img.yPlane + "px, -" + img.zPlane +"px)"; container.appendChild(img); }; imgLoc = ""; img.src= imgLoc + filename; img.alt = ""; waves[j] = img; j++; } function loadImages(){ for (var i = 0; i < waveSrc.length; ++i) { var filename = waveSrc[i]; preloadImage(filename); } } |
И наконец, мы двигаем изображения при помощи функции:
|
1 2 3 4 5 6 7 8 |
function moveImages(){ waves.forEach(function(image) { image.yPlane = image.yPlane - 2; image.style.cssText = "transform: translate3d(" + image.xPlane+"px, " + image.yPlane+"px, -" + image.zPlane + "px); z-index: " + image.zIndex; }); window.requestAnimationFrame(moveImages); } |
Чтобы все заработало, в конце скрипта необходимо вызвать подходящие функции:
|
1 2 3 4 5 |
loadImages(); window.addEventListener("load", function() { window.requestAnimationFrame(moveImages); }); |
Улучшения
Наш код – это прототип, и он немного грубоват. В него можно внести очевидные улучшения:
Сейчас наш скрипт продолжает работать, когда все изображения исчезают в верхней части контейнера, т.е. он работает бесконечно. В идеале, скрипт должен вырезать изображения из начала массива после их исчезновения и вставлять их в самый низ экрана.
Как ни парадоксально, лучше сделать расположение изображений более предсказуемым. Прямо сейчас в нашем демо изображение может появиться точно за другим изображением или почти на одном уровне с ним (т.е. оба изображения будут двигаться с одной скоростью). Чтобы избежать подобных ситуаций, мне понадобилось бы сравнивать значения расположения новых изображений с теми, что уже прописаны в массиве. Если значения очень близки, мне пришлось бы генерировать новое случайное значение.
Мы создали технику с автоматической прокруткой. Если вы хотите привязать движение изображений к позиции скроллбара на странице, вы можете изменять расположение изображений по window.scrollY.
Источник: //thenewcode.com/
Редакция: Команда webformyself.




