CSS Infinite 3D Sliders PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

CSS Infinite 3D слайдери

У цій серії, ми створювали слайдери зображень лише з HTML і CSS. Ідея полягає в тому, що ми можемо використовувати ту саму розмітку, але інший CSS, щоб отримати надзвичайно різні результати, незалежно від того, скільки зображень ми додаємо. Ми почали з круглого повзунка, який нескінченно обертається, щось на зразок фіджет-спиннера, який містить зображення. Потім ми зробили один, який гортає стопку фотографій.

Цього разу ми поринаємо у третій вимір. Спочатку це здасться важким, але багато коду, який ми розглядаємо, є саме тим, що ми використовували в перших двох статтях цієї серії, з деякими змінами. Отже, якщо ви тільки зараз починаєте розглядати цю серію, я б запропонував переглянути інші, щоб дізнатися про контекст понять, які ми тут використовуємо.

Серія слайдерів CSS

Це те, до чого ми прагнемо:

На перший погляд здається, що перед нами обертовий куб із чотирма зображеннями. Але насправді ми маємо справу з шістьма зображеннями. Ось повзунок під іншим кутом:

Тепер, коли ми маємо гарне візуальне уявлення про те, як розташовані зображення, давайте розберемо код, щоб побачити, як ми цього досягнемо.

Основне налаштування

Той самий HTML, що й інші повзунки, які ми використовували для інших повзунків:

І знову ми використовуємо CSS Grid, щоб розмістити зображення в стеку одне на одному:

.gallery {
  display: grid;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 160px;
  aspect-ratio: 1;
  object-fit: cover;
}

Анімація

Логіка цього повзунка дуже схожа на круговий повзунок з першої статті. Насправді, якщо ви ще раз перевірите відео вище, ви побачите, що зображення розміщено таким чином, що створюється багатокутник. Після повного оберту він повертається до першого зображення.

Ми покладалися на CSS transform-origin та animation-delay властивості для цього першого повзунка. Та сама анімація застосовується до всіх елементів зображення, які обертаються навколо однієї точки. Потім, використовуючи різні затримки, ми правильно розташовуємо всі зображення навколо великого кола.

Реалізація буде дещо іншою для нашого 3D-слайдера. Використання transform-origin не працюватиме тут, тому що ми працюємо в 3D, тому ми будемо використовувати transform замість того, щоб правильно розмістити всі зображення, потім поверніть контейнер.

Ми знову використовуємо Sass, щоб ми могли переглянути кількість зображень і застосувати наші трансформації:

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
     transform: 
       rotate(#{360*($i - 1) / $n}deg) /* 1 */
       translateY(50% / math.tan(180deg / $n)) /* 2 */ 
       rotateX(90deg); /* 3 */
  }
}

Вам може бути цікаво, чому ми стрибаємо відразу до Sass. Ми почали з фіксованої кількості зображень, використовуючи ванільний CSS в інших статтях, перш ніж узагальнити код за допомогою Sass для врахування будь-якої кількості (N) зображень. Що ж, я думаю, ви зараз зрозуміли ідею, і ми можемо припинити всю цю пошукову роботу, щоб перейти до реальної реалізації.

Команда transform властивість приймає три значення, які я проілюстрував тут:

CSS Infinite 3D слайдери

Спочатку ми обертаємо всі зображення одне над одним. Кут повороту залежить від кількості зображень. для N зображень, маємо приріст, який дорівнює 360deg/N. Тоді ми translate усі зображення на однакову величину таким чином, щоб їхні центральні точки зустрілися з боків.

Показує стос зображень, розташованих рівно по колу з червоною лінією, що проходить через центральну точку зображень.
CSS Infinite 3D слайдери

Є якась нудна геометрія, яка допомагає пояснити, як усе це працює, але відстань дорівнює 50%/tan(180deg/N). Ми мали справу з подібним рівнянням, створюючи круговий повзунок ( transform-origin: 50% 50%/sin(180deg/N) ).

Нарешті, ми повертаємо зображення навколо осі x на 90deg щоб отримати потрібний нам порядок. Ось відео, яке ілюструє, що робить остання ротація:

Тепер все, що нам потрібно зробити, це повернути весь контейнер, щоб створити нескінченний слайдер.

.gallery {
  transform-style: preserve-3d;
  --_t: perspective(280px) rotateX(-90deg);
  animation: r 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes r {
  0%, 3% {transform: var(--_t) rotate(0deg); }
  @for $i from 1 to $n {
    #{($i/$n)*100 - 2}%, 
    #{($i/$n)*100 + 3}% {
      transform: var(--_t) rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: var(--_t) rotate(-360deg); }
}

Цей код може бути важко зрозуміти, тому давайте повернемося на хвилинку назад і переглянемо анімацію, яку ми створили для круглого повзунка. Ось що ми писали в першій статті:

.gallery {
  animation: m 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes m {
  0%, 3% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100 - 2}%,
    #{($i / $n) * 100 + 3}% { 
      transform: rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: rotate(-360deg); }
}

Ключові кадри майже ідентичні. Ми маємо однакові відсоткові значення, той самий цикл і те саме обертання.

Чому обидва однакові? Бо логіка у них однакова. В обох випадках зображення розташовані навколо круглої форми, і нам потрібно повернути все, щоб показати кожне зображення. Ось як я зміг скопіювати ключові кадри з кругового слайдера та використати той самий код для нашого 3D-повзунка. Єдина відмінність полягає в тому, що нам потрібно обертати контейнер -90deg вздовж осі x, щоб побачити зображення, оскільки ми вже повернули їх 90deg на одній осі. Потім додаємо нотку perspective щоб отримати ефект 3D.

Це воно! Наш слайдер готовий. Ось знову повна демонстрація. Все, що вам потрібно зробити, це додати скільки завгодно зображень і оновити одну змінну, щоб це запрацювало.

Вертикальний 3D слайдер

Оскільки ми граємо в 3D просторі, чому б не зробити вертикальну версію попереднього слайдера? Останній обертається вздовж осі z, але ми також можемо рухатися вздовж осі x, якщо хочемо.

Якщо ви порівняєте код для обох версій цього слайдера, ви можете не одразу помітити різницю, оскільки це лише один символ! Я замінив rotate() з rotateX() всередині ключових кадрів і зображення transform. Це воно!

Слід зазначити, що rotate() еквівалентна rotateZ(), тому зміною осі від Z до X трансформуємо повзунок з горизонтального варіанту у вертикальний.

Кубічний слайдер

Ми не можемо говорити про 3D у CSS без нього говорити про кубики. І так, це означає, що ми збираємося створити іншу версію слайдера.

Ідея цієї версії повзунка полягає в тому, щоб створити фактичну форму куба із зображеннями та обертати весь предмет навколо іншої осі. Оскільки це куб, ми маємо справу з шістьма гранями. Ми використаємо шість зображень, по одному для кожної грані куба. Отже, без Sass, але повернемося до ванільного CSS.

Ця анімація трохи приголомшлива, чи не так? З чого ви взагалі починаєте?

У нас є шість граней, тому нам потрібно виконати принаймні шість поворотів, щоб кожне зображення отримало поворот. Ну, власне, нам потрібно п’ять поворотів — останній повертає нас до першої грані зображення. Якщо ви візьмете кубик Рубіка — або якийсь інший об’єкт у формі куба, як-от гральні кістки — і покрутите його рукою, ви добре зрозумієте, що ми робимо.

.gallery {
  --s: 250px; /* the size */

  transform-style: preserve-3d;
  --_p: perspective(calc(2.5*var(--s)));
  animation: r 9s infinite cubic-bezier(.5, -0.5, .5, 1.5);
}

@keyframes r {
  0%, 3%   { transform: var(--_p); }
  14%, 19% { transform: var(--_p) rotateX(90deg); }
  31%, 36% { transform: var(--_p) rotateX(90deg) rotateZ(90deg); }
  47%, 52% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
  64%, 69% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg); }
  81%, 86% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg); }
  97%, 100%{ transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
}

Команда transform властивість починається з нуля поворотів, і до кожного стану ми додаємо новий поворот на певній осі, доки не досягнемо шести обертів. Тоді ми повертаємося до першого зображення.

Не забуваймо про розміщення наших зображень. Кожен прикладається до грані куба за допомогою transform:

.gallery img {
  grid-area: 1 / 1;
  width: var(--s);
  aspect-ratio: 1;
  object-fit: cover;
  transform: var(--_t,) translateZ(calc(var(--s) / 2));
}
.gallery img:nth-child(2) { --_t: rotateX(-90deg); }
.gallery img:nth-child(3) { --_t: rotateY( 90deg) rotate(-90deg); }
.gallery img:nth-child(4) { --_t: rotateX(180deg) rotate( 90deg); }
.gallery img:nth-child(5) { --_t: rotateX( 90deg) rotate( 90deg); }
.gallery img:nth-child(6) { --_t: rotateY(-90deg); }

Ви, мабуть, думаєте, що за значеннями, які я там використовую, стоїть дивна складна логіка, чи не так? Ну ні. Все, що я зробив, це відкрив DevTools і погрався з різними значеннями обертання для кожного зображення, доки я не зробив це правильно. Це може здатися дурним, але це працює — особливо тому, що у нас є фіксована кількість зображень, і ми не шукаємо щось, що підтримує N зображення.

Насправді забудьте про значення, які я використовую, і спробуйте зробити розміщення самостійно як вправу. Почніть із усіх зображень, складених одне на одне, відкрийте DevTools і вперед! Ймовірно, ви отримаєте інший код, і це цілком нормально. Існують різні способи розміщення зображень.

Який трюк з комою всередині var()? Це помилка?

Це не помилка, тому не видаляйте її! Якщо ви видалите його, ви помітите, що це впливає на розміщення першого зображення. Ви можете побачити це в моєму коді, який я визначив --_t для всіх зображень, крім першого, тому що мені потрібен лише переклад. Ця кома повертає змінну до нульового значення. Без коми ми не матимемо резервного варіанту, і все значення буде недійсним.

Від специфікація:

Примітка. Тобто var(--a,) є дійсною функцією, яка вказує, що якщо --a властивість користувача недійсна або відсутня, var()` не слід замінювати ні на що.

Випадковий повзунок куба

Трохи випадковості може бути гарним покращенням для такого роду анімації. Отже, замість того, щоб обертати кубик у послідовному порядку, ми можемо кинути кубик, так би мовити, і дозволити кубику котитися як завгодно.

Круто правда? Не знаю як вам, а мені ця версія більше подобається! Так цікавіше і переходи приємно спостерігати. І вгадайте що? Ви можете пограти зі значеннями, щоб створити свій власний повзунок випадкового куба!

Логіка насправді зовсім не випадкова — вона просто так здається. Ви визначаєте a transform на кожному ключовому кадрі, що дозволяє показати одне обличчя і… ну, ось і все! Ви можете вибрати будь-яке замовлення.

@keyframes r {
  0%, 3%   { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
  14%,19%  { transform: var(--_p) rotate3d(-1, 1, 0,180deg); }
  31%,36%  { transform: var(--_p) rotate3d( 0,-1, 0, 90deg); }
  47%,52%  { transform: var(--_p) rotate3d( 1, 0, 0, 90deg); }
  64%,69%  { transform: var(--_p) rotate3d( 1, 0, 0,-90deg); }
  81%,86%  { transform: var(--_p) rotate3d( 0, 1, 0, 90deg); }
  97%,100% { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
}

Я використовую rotate3d() цього разу, але я все ще покладаюся на DevTools, щоб знайти значення, які мені здаються «правильними». Не намагайтеся знайти зв’язок між ключовими кадрами, оскільки його просто немає. Я визначаю окремі перетворення, а потім спостерігаю за «випадковим» результатом. Переконайтеся, що перше зображення є першим і останнім кадрами відповідно, і показуйте різні зображення на кожному з інших кадрів.

Ви не зобов'язані використовувати a rotate3d() трансформуватися, як я. Ви також можете ланцюгувати різні оберти, як ми робили в попередньому прикладі. Пограйте і подивіться, що ви можете придумати! Я чекаю, коли ви поділитеся зі мною своєю версією в розділі коментарів!

Підводячи підсумок

Сподіваюся, вам сподобався цей маленький серіал. Ми створили кілька цікавих (і кумедних) слайдерів, одночасно вивчаючи всі види концепцій CSS — від розміщення сітки та порядку стекування до затримок анімації та трансформацій. Нам навіть довелося пограти з трішкою Sass, щоб прокрутити масив елементів.

І ми зробили все це з тим самим HTML для кожного повзунка, який ми створили. Як це круто? CSS надзвичайно потужний і здатний зробити багато чого без допомоги JavaScript.

Часова мітка:

Більше від CSS-хитрощі