Легкий параллакс эффект с помощью JavaScript и CSS трансформаций

Легкий параллакс эффект с помощью JavaScript и CSS трансформаций

От автора: в последнее время ряд сайтов, в том числе рекламная страница Bioware игры Mass Effect Andromeda и работа агентства Active Theory Under Armour получили параллакс эффект, когда движение мыши связано с движением элемента на странице в противоположном направлении. Я захотел воссоздать этот эффект на чистом JavaScript и современных свойствах CSS. Пример моих стараний можно увидеть ниже.

Итоговое демо урока.

Выходим на ринг

Разметка состоит из контейнера div, изображения, заголовка и основного текста (взятого из произведения Джека Лондона Кусок мяса) внутри еще одного div:

<div id="boxercontainer">
  <img src="boxer.png" alt>
  <div>
 <h1>The Boxer</h1>
 <p>Well, a man had only so many fights in him, to begin with…
  </div>
</div>

Боксера мы отделили от фона и сохранили в PNG с альфа маской. С помощью конвертации изображения в 16-bit мы уменьшили размер файла.

Стили внешнего элемента #boxercontainer: обратите внимание, что background-image сделан немного больше контейнера и расположен чисто по центру. Это очень важно, но об этом позже:

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее
#boxercontainer {
  width: 80%;
  max-width: 900px;
  margin: 0 auto;
  background-image: url(concrete-background.jpg);
  position: relative;
  padding-bottom: 45%;
  background-size: 120% 120%;
  background-position: 50% 50%;
  overflow: hidden;
  min-height: 650px;
}

У внутреннего блока div задана прозрачность, светло-серый фон для увеличения контрастности текста:

#boxercontainer div {
  position: absolute;
  width: 60%;
  left: 20px;
  top: 20px;
  border: 1px solid #fff;
  padding: 2rem;
  background: rgba(0,0,0,0.2);
}

Изображение позиционировано абсолютно и опущено так, чтобы нижняя часть ног боксера выходила за пределы родительского элемента и скрывалась при помощи overflow: hidden. Вокруг боксера применен фильтр drop-shadow, который дает намного меньший размер файла, нежели рисовать тень в PNG. Как мы сейчас увидим, такая тень делает изображение более динамичным.

#boxercontainer img { 
  position: absolute;
  bottom: -35px;
  right: 50px;
  width: 40%;
  filter: drop-shadow(-200px 200px 50px #000);
  padding: 1rem;
  z-index: 2;
}

Боксеру присвоено свойство z-index со значением 2, что помещает его визуально выше блока div с текстом, но из-за этого тень будет падать на слова. Чтобы поправить это, я изменил текст:

Легкий параллакс эффект с помощью JavaScript и CSS трансформаций

#boxercontainer p {
  position: relative;
  z-index: 3;
}

Значение z-index у текста теперь больше, и тень проваливается под текст, но расположена выше рамки блока div.

Центрируем

Основная идея параллакс эффекта заключается в том, чтобы найти центр затрагиваемого элемента. Расстояние от центра до курсора будет смещать элемент на такое же расстояние, но в противоположную сторону.

Легкий параллакс эффект с помощью JavaScript и CSS трансформаций

Скрипт начинает с идентификации элементов. Атрибут id в JS автоматически превращается в ссылку, а для получения боксера используется querySelector:

const boxer = boxercontainer.querySelector("img"),
maxMove = boxercontainer.offsetWidth / 30,
boxerCenterX = boxer.offsetLeft + (boxer.offsetWidth / 2),
boxerCenterY = boxer.offsetTop + (boxer.offsetHeight / 2);

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

Кроме того, нам нужно определить положение мыши внутри boxercontainer, для чего я использую функцию:

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее
function getMousePos(xRef, yRef) {
  let panelRect = boxercontainer.getBoundingClientRect();
  return {
 x: Math.floor(xRef - panelRect.left) / 
 (panelRect.right - panelRect.left)*boxercontainer.offsetWidth,
 y: Math.floor(yRef - panelRect.top) / 
 (panelRect.bottom - panelRect.top) * boxercontainer.offsetHeight
 };
}

Порхай как бабочка

Такие эффекты обычно реагируют на движение мыши на странице:

document.body.addEventListener("mousemove", function(e) {
  let mousePos = getMousePos(e.clientX, e.clientY),
  distX = mousePos.x - boxerCenterX,
  distY = mousePos.y - boxerCenterY;
  if (Math.abs(distX) < 500 && distY < 200) {
  boxer.style.transform = 
 "translate("+(-1 * distX) / 12 + "px," + (-1 * distY) / 12 + "px)";
  }
})

Переменная distX – горизонтальное расстояние от текущего положения мыши до изначального центра изображения боксера. Переменная distY – вертикальное расстояние. Если разница по вертикали (положительная или отрицательная) меньше 500px, а горизонтальное расстояние меньше 200px, мы двигаем боксера с помощью CSS трансформаций:

оба расстояния умножаются на -1 (положительное значение становится отрицательным и наоборот);

результат делится на 12, чтобы уменьшить отношение движения между мышью и изображением (соотношение 1:1 между положением мыши и изображением приведет к слишком резким движениям).

Сейчас стоит сказать, что я никогда бы не предложил использовать эту технику для UI элементов: попасть по движущейся цели очень сложно для пользователей с проблемами зрения и движения. Возможное решение описано ниже.

Когда мы двигаем голову, позицию меняют не только элементы переднего плана. Объекты на заднем фоне также смещаются в противоположную сторону. Представьте объект, расположенный в нескольких сантиметрах от стены: переместив объект вправо, для вас перспектива изменится для стены и объекта.

Чтобы воссоздать такой эффект, я также сдвигаю background-image бетонной стены. В колбэк функцию addEventListener нужно добавить код ниже в конец скрипта:

boxercontainer.style.backgroundPosition = 
 `calc(50% + ${distX / 50}px) calc(50% + ${distY / 50}px)`;

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

Я двигаю изображение на основе положения мыши, а не касаний, так как взрослые, как правило, не лапают постоянно экран.

Исключение

Есть общее правило. Параллакс эффект хорошо работает на больших экранах и ноутбуках и совсем не работает на маленьких разрешениях. Эффект создан на JS, поэтому мы должны определять ширину экрана с помощью matchMedia:

let fluidboxer = window.matchMedia("(min-width: 726px)");

Условие if для движения изображения и фона меняется на:

if (Math.abs(distX) < 500 && distY < 200 && fluidboxer.matches) { … }

В CSS @media запросах есть дополнительные изменения для смены дизайна на маленьких экранах. Более подробно в CodePen демо.

Для людей с различными расстройствами

Параллакс эффект может оказать негативное воздействие на людей с расстройствами вестибулярного аппарата (чувствительных к визуальному движению), вплоть до тошноты и припадков. Было бы хорошо, как минимум, показывать предупреждение или какой-то другой знак того, что на странице есть эффект движения. Разработчики браузеров сейчас работают над настройкой «уменьшить движение». В ближайшем будущем движение будет определяться с помощью @media запроса. Эффекты типа палаллакса будут автоматически выключаться на страницах для людей с такими расстройствами.

Заключение

CSS трансформации и JS события движения мыши – относительно простой и легкий способ создания параллакс эффекта с минимумом вычислений. В будущих статьях я более подробно раскрою эффекты такого типа.

Источник: http://thenewcode.com/

Редакция: Команда webformyself.

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее
Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree