Автор оригинала: Vincent Humeau.
В этой статье мы собираемся создать небольшую 3D-сцену, где пользователь может прокрутить на ось Z. Вы можете найти последний код этого руководства на Github и демонстрация, если вы будете следовать этим ссылка Отказ
Эта статья предполагает, что у вас уже есть некоторые знания о CSS и JavaScript. Мы собираемся использовать пользовательские свойства CSS, поэтому, если вы не знакомы с этим, вы можете прочитать CSS пользовательские свойства – Cheatsheet Отказ
Введение в CSS 3D
Говоря о CSS 3D, мы действительно говорим о CSS3 Transform 3D. Этот метод позволяет нам использовать трансформировать Свойство CSS для установки перспективы или вращения на оси Z для наших элементов DOM.
Чтобы быть разрешенным оказывать наши элементы DOM в трехмерном пространстве, нам нужно взглянуть на следующие свойства:
- Перспектива
- Перспективное происхождение
- Преобразовывать Z.
Перспектива
Перспектива это свойство CSS, которое устанавливает расстояние между и пользователем. Чем меньше – это перспективное значение, и тем больше будет искажение нашей сцены. (Попробуйте изменить значение CONGEPERSPERSPERSPECTION в примере кодепена ниже).
.container-scene { perspective: 100px; }Значение Перспектива это Блок длины Отказ
Попробуйте установить значение Сценаперскакция до 0 и 70 в примере ниже. Вы можете заметить, что наш куб не имеет перспективы вообще, если его значение установлено значение 0. Если значение установлено значение 70, вы можете увидеть действительно сильное искажение перспективы куба. Чем меньше перспективное значение, глубже это.
Чтобы иметь возможность сделать 3D-пространство, нам нужно указать Стиль трансформации: PROSERV-3D; на дочерних элементах. В приведенном выше примере это установлено нашему .cube . По умолчанию элементы сплющены.
.container-scene {
perspective: 400px;
}
.container-scene .cube {
transform-style: preserve-3d;
}Перспективное происхождение
Это свойство в основном позволяет нам перемещать точку исчезновения нашей 3D-сцены.
.container-scene {
perspective: 400px;
perspective-origin: 50% 100%; /*X position value, Y position value*/
}
.container-scene .cube {
transform-style: preserve-3d;
}Для обоих X, так и Y мы можем установить положение, используя проценты. Но мы также можем использовать следующие значения:
положение x:
левый%Центр%Правильно%
позиция Y.
верх%Центр%снизу%
В следующем примере вы можете изменить значение перспективность и Перспектива Отказ
Преобразовывать Z.
Мы уже упоминали ранее, что трансформировать Свойство CSS позволяет нам установить наши элементы в трехмерном пространстве.
Преобразование поставляется с различными функциями для преобразования наших элементов в 3D:
- Rotatex (угол) – MDN
- Рогатистый (угол) – MDN
- Rotatez (угол) – MDN
- Translatez (TZ) – MDN
- Scalez (SZ) – MDN
Как мы видели на иллюстрации в Перспектива Раздел, translatez () Позволяет нам расположить элемент вдоль оси z 3D-пространства. Поочередно мы можем использовать translate3d (x, y, z) CSS функция.
В следующем примере вы можете играть с положением Z-оси .Cube и .лицо- Изменяя значение CubeTranslatez и Cubefacestranslatez .
Теперь, когда у нас есть хорошее понимание того, как CSS 3D-работы мы собираемся создать 3D-сцену, где мы сможем прокрутить ось Z.
Установить сцену
Мы собираемся создать страницу, которая перечисляет все фильмы студии Ghibli. Каждый фильм будет картой, расположенную на оси Z нашей сцены. Не стесняйтесь вилкой или Скачать Следующий кодепен как стартовый материал для последующего. Я использую Axios с Студия Ghibli API заполнить эту страницу.
Если вы хотите следить со своим собственным контентом, нам понадобится следующая разметка:
Стайлинг
Во-первых, мы собираемся установить наши CSS пользовательские свойства (CSS переменные). Некоторые из этих переменных будут преобразованы с использованием JS. Они собираются помочь нам взаимодействовать со сценой.
:root {
--scenePerspective: 1;
--scenePerspectiveOriginX: 50;
--scenePerspectiveOriginY: 30;
--itemZ: 2; // Gap between each cards
--cameraSpeed: 150; // Where 1 is the fastest, this var is a multiplying factor of --scenePerspective and --filmZ
--cameraZ: 0; // Initial camera position
--viewportHeight: 0; // Viewport height will allow us to set the depth of our scene
}.viewport позволит нам установить высоту окна. Позже мы будем использовать его, чтобы установить глубину сцены и использовать прокрутку для перемещения в оси z.
.viewport {
height: calc(var(--viewportHeight) * 1px);
}.scene3D-контейнер Устанавливает перспективу сцены и перспективное происхождение. Это зафиксировано положение, поэтому он остается на экране. Мы также собираемся установить перспективное происхождение.
.viewport .scene3D-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
perspective: calc(var(--scenePerspective) * var(--cameraSpeed) * 1px);
perspective-origin: calc(var(--scenePerspectiveOriginX) * 1%) calc( var(--scenePerspectiveOriginY) * 1% );
will-change: perspective-origin;
transform: translate3d( 0, 0, 0 ); //Allows Hardware-Accelerated CSS, so transitions are smoother
}.scene3d Устанавливает положение нашей сцены на оси Z, это будет вести себя немного похоже на перемещение камеры на Z-оси. Но на самом деле мы перемещаем сцену, а камера (Viewport) исправлена. В остальной части этой статьи мы собираемся использовать сравнение камеры. .scene3d. занимает полную высоту и ширину Viewport.
.viewport .scene3D-container .scene3D {
position: absolute; top: 0;
height: 100vh;
width: 100%;
transform-style: preserve-3d;
transform: translateZ(calc(var(--cameraZ) * 1px));
will-change: transform;
}Последнее, но не менее важное, мы собираемся позиционировать наши карты на сцене. Все предметы расположены абсолютным. Нечетные предметы расположены слева, даже справа.
Мы используем SCSS для программного перевода каждого элемента. На Х и Уход Ось, мы случайным образом перевезем их от -25% до 25% для X, от -50% и 50% для Y. Мы используем @ for петля, поэтому каждый элемент может быть переведен на Z-ось умножить на их индексы.
.viewport .scene3D-container .scene3D {
> div {
position: absolute;
display: block;
width: 100%;
top: 40%;
@media only screen and (min-width: 600px) {
width: 45%;
}
&:nth-child(2n) { left: 0; }
&:nth-child(2n + 1) { right: 0; }
@for $i from 0 through 25 {
&:nth-child(#{$i}) {
transform: translate3D( random(50) - 25 * 1%, random(100) - 50 * 1%, calc(var(--itemZ) * var(--cameraSpeed) * #{$i} * -1px) );
}
}
}
}CSS теперь сделан, и у нас есть 3D-сцена. В следующих частях этой статьи мы собираемся написать какой-то JavaScript, который позволит нам ориентироваться в сцене.
Чтобы иметь возможность прокрутить, нам нужно сначала установить значение --viewportheight что эмулирует глубину сцены.
Глубина сцены равна добавлению следующего:
- Высота окна пользователя
-
.scene3D-контейнерПерспектива = & gt; VAR (- сценарки) * var (- cameraspeed) - Переведенное значение Z нашего последнего элемента = & g
t; var (- itemz) * var (- cameraspeed) * items.lenприоритет
Давайте создадим setsceneheight () Функция, которая обновит значение --viewportheight в процессе.
document.addEventListener("DOMContentLoaded", function() {
setSceneHeight();
});
function setSceneHeight() {
const numberOfItems = films.length; // Or number of items you have in `.scene3D`
const itemZ = parseFloat(
getComputedStyle(document.documentElement).getPropertyValue("--itemZ")
);
const scenePerspective = parseFloat(
getComputedStyle(document.documentElement).getPropertyValue(
"--scenePerspective"
)
);
const cameraSpeed = parseFloat(
getComputedStyle(document.documentElement).getPropertyValue("--cameraSpeed")
);
const height =
window.innerHeight +
scenePerspective * cameraSpeed +
itemZ * cameraSpeed * numberOfItems;
// Update --viewportHeight value
document.documentElement.style.setProperty("--viewportHeight", height);
}Наша страница состоит теперь прокрутка, но мы все еще не можем прокрутить. Нам нужно добавить слушатель события, который будет прослушивать прокрутку пользователя. Событие прокрутки позвонит A MoveCamera () функция. Это обновит стоимость --cameraz со значением window.pageyoffset Отказ
document.addEventListener("DOMContentLoaded", function() {
window.addEventListener("scroll", moveCamera);
setSceneHeight();
});
function moveCamera() {
document.documentElement.style.setProperty("--cameraZ", window.pageYOffset);
}
function setSceneHeight() {
// ...
}Переместить угол камеры
Наконец, давайте сделаем нашу сцену немного более динамичной. На MouseMove событие Мы собираемся изменить значения СценаperspectionOriginx и СценаPersPientoriginy Отказ Это даст иллюзию, что камера движется. Предметы останутся прямо в сцене. Если вы хотите дать более реалистичное движение вращения камеры, вы можете подать заявку Rotate3D () на сцене.
Во-первых, мы собираемся хранить начальные значения этих двух переменных в Перспективность объект. Мы собираемся установить Perspectorigin.maxgap Значение, которое будет ограничивать максимальные и минимальные значения переменных. Например, если СценаPersPientoriginy равно 50%. На Маусемове новая стоимость составит от 40% до 60%.
const perspectiveOrigin = {
x: parseFloat(
getComputedStyle(document.documentElement).getPropertyValue(
"--scenePerspectiveOriginX"
)
),
y: parseFloat(
getComputedStyle(document.documentElement).getPropertyValue(
"--scenePerspectiveOriginY"
)
),
maxGap: 10
};Если курсор пользователя находится в центре экрана, мы установим значения --scenePerspeactionInx и --scenePerspeactionInx. как начальные. Чем дальше курсор перемещается от центра, тем больше эти значения будут увеличиваться/уменьшаться. Если пользователь перемещается в верхний левый угол, значения будут увеличиваться, а в правом нижнем углу они уменьшится.
movecameraugle () Функция собирается обновить значения:
xgapиygapВерните положение мыши пользователя в процентах на оси X и Y, по сравнению с центром окна.NewPerspeectionOriginxиNewPersPeactoriginyвернуть новое перспективное происхождение.
document.addEventListener("DOMContentLoaded", function() {
window.addEventListener("scroll", moveCamera);
window.addEventListener("mousemove", moveCameraAngle);
setSceneHeight();
});
function moveCameraAngle(event) {
const xGap =
(((event.clientX - window.innerWidth / 2) * 100) /
(window.innerWidth / 2)) *
-1;
const yGap =
(((event.clientY - window.innerHeight / 2) * 100) /
(window.innerHeight / 2)) *
-1;
const newPerspectiveOriginX =
perspectiveOrigin.x + (xGap * perspectiveOrigin.maxGap) / 100;
const newPerspectiveOriginY =
perspectiveOrigin.y + (yGap * perspectiveOrigin.maxGap) / 100;
document.documentElement.style.setProperty(
"--scenePerspectiveOriginX",
newPerspectiveOriginX
);
document.documentElement.style.setProperty(
"--scenePerspectiveOriginY",
newPerspectiveOriginY
);
}Наша сцена теперь закончена. Я надеюсь, что вам понравилось эту статью.
Ресурсы
- Перспектива – Кодрос
- Перспектива – MDN.
- Стиль трансформации – Codrops
- Стиль преобразования – MDN
- Перспективное происхождение – MDN
- Вещи, чтобы осторожны при работе с CSS 3D – CSS-Tricks
Читать дальше моих статей в блоге в vinceumo.github.io .
Оригинал: “https://www.freecodecamp.org/news/css-3d-scrolling-on-the-z-axis-92503c3ecf3f/”