Создаем 3D куб на чистом CSS

16.02.2022

Во многих книгах по 3D графике можно увидеть пример куба, с текстом / текстурами на каждой грани. Нарисовать такое на canvas с использованием javascript, проблемы не составляет, но мало кто знает, что сделать такое можно и на чистом CSS.

В данной статье мне хотелось бы показать несколько примеров 3D-преобразования на CSS.

Основы

Для начала давайте ознакомимся со свойствами perspective и transform: rotate();.

Простой, пример, прямоугольник, в котором находиться повернутый блок:

pic1

 
<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>

И небольшое отступление, вместо цветной грани можно использовать картинку.

pic1

это потребует небольших правок:

 

<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);


Категории: CSS
Яндекс.Метрика