Свободновращающийся элемент в 3D пространстве с помощью CSS переменных

Свободновращающийся элемент в 3D пространстве с помощью CSS переменных

От автора: недавно один из моих учеников спросил меня, можно ли создать элемент на экране, который можно вращать в любую сторону при помощи мыши или касаний. На первом семестре я рассказываю только о HTML5 и CSS, поэтому ответ был «нет, без JavaScript нельзя». Но в этом решении всего пара строк JS, и в нем очень интересно используются CSS переменные.

Объекты в пространстве

Разметка демо состоит всего из одного элемента:

<img src="dasha.jpg" srcset="dasha-2x.jpg 2x" alt>

(Вы можете поместить на странице сколь угодно много элементов, я же оставил всего один для простоты и ясности).

Тегу body заданы свойства margin: 0 и min-height: 100vh. Для центрирования элементов на странице используется flexbox:

body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  perspective: 60vw;
  margin: 0;
  --mouseX: 0deg;
  --mouseY: 0deg;
}

Кроме того, была задана CSS 3D перспектива, а также две CSS переменные. Переменные используются для стилизации изображения:

img {
  width: 80vmin;
  height: 80vmin;
  transform: rotateX(calc(var(--mouseY)))
    rotateY(calc(var(--mouseX)));
}

Обратите внимание, что, так как мы используем больше одной переменной в свойстве transform, их необходимо обернуть в функцию calc(), чтобы не было ошибок синтаксиса. В ближайшее время, когда свойства rotateX и Y станут нативными свойствами CSS, использовать функцию calc() будет необязательно.

У изображения должны быть заданы высота и ширина, иначе flexbox растянет его.

Отслеживание позиции

Код JS начинается с нахождения изображения:

const img = document.getElementsByTagName("img")[0];

Обычно CSS переменные задаются в CSS и используются внутри стилей, но их можно задавать и через JS при помощи setProperty. Я сделал это в функции, которая берет текущую позицию указателя мыши, определяет высоту и ширину окна браузера (делит их пополам), после чего на основе этой информации определяется правильный угол наклона изображения:

function sway(xPos, yPos) {
  let wh = window.innerHeight / 2,
  ww = window.innerWidth / 2;
  document.body.style.setProperty("--mouseX", (xPos - ww) / 25+"deg");
  document.body.style.setProperty("--mouseY", (yPos - wh) / 25+"deg");
}

Функция инициируется как движением мыши, так и касанием:

document.addEventListener("mousemove", function(e) {
  sway(e.clientX,e.clientY);
})

document.addEventListener("touchmove", function(e) {
    e.preventDefault();
    var touch = e.targetTouches[0];
    if (touch) {
        sway(touch.pageX, touch.pageY);
    }
});

Обратите внимание, что значения в переменных поменяны местами: движение по оси Х поворачивает изображение по оси У и наоборот.

Сила переменных

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

Если вам нужна поддержка в MS Edge и IE (и если вы хотите обойти текущие ограничения в Firefox), функцию можно было бы написать на JS:

function sway(xPos, yPos) {
  img.style.transform = "rotateX("+(yPos - wh) / 25+"deg) rotateY("+(xPos - ww) / 25 +"deg)";
}

Помимо исходного кода я еще создал CodePen демо к этому уроку.

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

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

Самые свежие новости 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