Свободновращающийся елемент в 3D просторі з допомогою CSS змінних

39

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

Об’єкти у просторі

Розмітка демо складається всього з одного елемента:

(Ви можете помістити на сторінці скільки завгодно багато елементів, я ж залишив всього один для простоти і ясності).

Тегу 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 демо до цього уроку.