Во многих книгах по 3D графике можно увидеть пример куба, с текстом / текстурами на каждой грани. Нарисовать такое на canvas с использованием javascript, проблемы не составляет, но мало кто знает, что сделать такое можно и на чистом CSS.
В данной статье мне хотелось бы показать несколько примеров 3D-преобразования на CSS.
Основы
Для начала давайте ознакомимся со свойствами perspective и transform: rotate();.
Простой, пример, прямоугольник, в котором находиться повернутый блок:
<div class="wrapper--blue">
<div class="black--blue"></div>
</div>
.wrapper--aqua {
perspective: 400px;
width: 200px;
height: 200px;
border: 1px solid red;
margin: 50px;
}
.block--aqua {
background-color: aqua;
width: 100%;
height: 100%;
transform: rotateY(45deg);
}
Тут стоит обратить внимание на
rotateY(45deg) - угол поворота в 45 градусов и perspective(400px), тут сложно объяснить на пальцах, проще почитать в документации
Есть другой вариант, записи, через transform: perspective(400px) rotateY(45deg); который дает такой же эффект:
.wrapper--aqua {
/*perspective: 400px;*/
width: 200px;
height: 200px;
border: 1px solid red;
margin: 50px;
}
.block--aqua {
background-color: aqua;
width: 100%;
height: 100%;
transform: perspective(400px) rotateY(45deg);
}
Куб
Не будем ходить ходить вокруг и сразу посмотрим демонстрацию:
Front
Back
Right
Left
Top
Bottom
Но, тут все же оговорюсь - я немного слукавил и для данного примера использую JavaScript, но не для прорисовки куба и даже не для вращения, а только для изменения класса который отвечает, какая грань сейчас впереди.
Основная идея всего действ а:
.cube_wrapper {
/* Добавляем обертке перспективу */
perspective: 400px;
}
.cube {
/* Делаем сам куб 3Дшным */
transform-style: preserve-3d;
transform: translateZ(-100px);
transition: transform 1s;
}
.cube__side--front {
/* Каждой грани назначаем цвет и ориентацию в пространстве (поворот) */
background: hsla( 0, 100%, 50%, 0.7);
transform: rotateY( 0deg) translateZ(100px);
}
.cube.show-back {
/* вращаем куб, ставя вперёд нужной гранью */
transform: translateZ(-100px) rotateY(-180deg);
}
Сам HTML каркас:
<div class="wrapper">
<div id="cube" class="cube">
<div class="cube__side cube__side--front">Front</div>
<div class="cube__side cube__side--back">Back</div>
<div class="cube__side cube__side--right">Right</div>
<div class="cube__side cube__side--left">Left</div>
<div class="cube__side cube__side--top">Top</div>
<div class="cube__side cube__side--bottom">Bottom</div>
</div>
</div>
И небольшое отступление, вместо цветной грани можно использовать картинку.
это потребует небольших правок:
<div class="wrapper">
<div id="cube" class="cube">
<div class="cube__side cube__side--front">
<img src="01.jpg" alt="">
</div>
</div>
</div>
.cube__side img {
width: 100%;
height: 100%;
}
Собственно наша основа - CSS код:
.cube_wrapper {
width: 200px;
height: 200px;
border: 1px solid #CCC;
margin: 80px;
perspective: 400px;
}
.cube {
width: 200px;
height: 200px;
position: relative;
transform-style: preserve-3d;
transform: translateZ(-100px);
transition: transform 1s;
}
.cube__side {
position: absolute;
width: 200px;
height: 200px;
border: 2px solid black;
line-height: 200px;
font-size: 40px;
font-weight: bold;
color: white;
text-align: center;
}
.cube__side--front {
background: hsla( 0, 100%, 50%, 0.7);
transform: rotateY( 0deg) translateZ(100px);
}
.cube__side--right {
background: hsla( 60, 100%, 50%, 0.7);
transform: rotateY( 90deg) translateZ(100px);
}
.cube__side--back {
background: hsla(120, 100%, 50%, 0.7);
transform: rotateY(180deg) translateZ(100px);
}
.cube__side--left {
background: hsla(180, 100%, 50%, 0.7);
transform: rotateY(-90deg) translateZ(100px);
}
.cube__side--top {
background: hsla(240, 100%, 50%, 0.7);
transform: rotateX( 90deg) translateZ(100px);
}
.cube__side--bottom {
background: hsla(300, 100%, 50%, 0.7);
transform: rotateX(-90deg) translateZ(100px);
}
.cube.show-front {
transform: translateZ(-100px) rotateY( 0deg);
}
.cube.show-right {
transform: translateZ(-100px) rotateY( -90deg);
}
.cube.show-back {
transform: translateZ(-100px) rotateY(-180deg);
}
.cube.show-left {
transform: translateZ(-100px) rotateY( 90deg);
}
.cube.show-top {
transform: translateZ(-100px) rotateX( -90deg);
}
.cube.show-bottom {
transform: translateZ(-100px) rotateX( 90deg);
}
И javascript для смены активной стороны по таймеру:
function removeClasses(el, prefix) {
let classes = el.className.split(" ").filter(function(c) {
return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ").trim();
}
const cube = document.getElementById("cube");
let aSides = ["front", "back", "right", "left", "top", "bottom"]
function soRotate() {
const prefix = "show-";
removeClasses(cube, prefix);
const rand = Math.floor(Math.random() * aSides.length);
cube.classList.add(prefix + aSides[rand]);
}
setInterval(soRotate, 4000);