Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a moving 3d box with CSS transitions and Javascript

I have been playing with CSS trying to create a 3d box that you can select the face with vanilla javascript.

It is simply changing the className of the box divs and using the transition property to smoothly transition between locations.

here is a jsfiddle to show a working example http://jsfiddle.net/synthet1c/VdDmA/1/

It looks cool at the moment but it is not quite behaving the way I want... Does anyone know how I can keep the box solid when it is going through it's transition? currently if the face is going from 360deg to 90deg the face will rotate 270deg in the wrong direction. I understand why it's doing it but can't make a workaround for it.

I added all the browser prefixes but have only used it on firefox.

cheers for any advice,

Andrew #right, #back, #left, #front { height: 150px; width: 150px; position: absolute; border: 1px solid rgba(200,200,200,0.7); background-color: rgba(0,0,255,0.5); margin: 0px; }

.right{
    transform: rotateY(90deg) translatez(75px) translatex(-75px);
    transition: all 4s;
}

.back{
    transform: rotateY(180deg) translatez(0px) translatex(0px);
    transition: all 4s;
}

.left{
    transform: rotateY(270deg) translatez(75px) translatex(70px);
    transition: all 4s;
}

.front{
    transform: rotateY(0deg) translatez(150px) translatex(0px);
    transition: all 4s;
}

var id = function(elem){
    var theId = document.getElementById(elem);
    return theId;
}

function button1(){
    id('front').className = 'front';
    id('right').className = 'right';
    id('back').className = 'back';
    id('left').className = 'left';
}

function button2(){
    id('front').className = 'right';
    id('right').className = 'back';
    id('back').className = 'left';
    id('left').className = 'front';
}   

function button3(){
    id('front').className = 'back';
    id('right').className = 'left';
    id('back').className = 'front';
    id('left').className = 'right';
}   

function button4(){
    id('front').className = 'left';
    id('right').className = 'front';
    id('back').className = 'right';
    id('left').className = 'back';
}   
like image 588
synthet1c Avatar asked Nov 25 '12 08:11

synthet1c


1 Answers

It's actually pretty simple. You just need to do a check to see whether the difference, let's call it dif, in absolute value between the angle you're currently at and the angle you want to get to is over 180° and if it is, you rotate by 360° minus dif in absolute value, the direction of the rotation being given by the sign of dif.

I've also made some changes to the CSS, and if you want to understand more about how you can create a realistic looking cube, you can check my (really) detailed answer to a similar question.

demo

HTML:

<div class='buttons'>
    <button class='btn'>Front</button>
    <button class='btn'>Left</button>
    <button class='btn'>Back</button>
    <button class='btn'>Right</button>
</div>
<div class='house'>
    <div class='face front'>Front</div>
    <div class='face back'>Back</div>
    <div class='face right'>Right</div>
    <div class='face left'>Left</div>
</div>

Relevant CSS:

body /* or parent of .house */ { perspective: 45em; }
.house { position: relative; transform-style: preserve-3d; transition: 1s; }
.house, .face { width: 10em; height: 10em; }
.face {
    box-sizing: border-box;
    position: absolute;
    padding: 1em;
}
.front { transform: translateZ(5em); background: rgba(255, 165, 0, .75); }
.back { 
    transform: rotateY(180deg) translateZ(5em);
    background: rgba(30, 144, 255, .75);
}
.right {
    transform: rotateY(90deg) translateZ(5em);
    background: rgba(220, 20, 60, .75);
}
.left {
    transform: rotateY(-90deg) translateZ(5em);
    background: rgba(127, 255, 0, .75);
}

JavaScript:

(function(){
    var btnsEl = document.querySelector('.buttons'), currentAngle = 0;
    btnsEl.addEventListener('click', function(e){
        var b = e.target.innerHTML.toLowerCase(), 
            house = document.querySelector('.house'), 
            btns = {'front': 0, 'left': 90, 'back': 180, 'right': -90}, 
            dif = btns[b] - currentAngle%360;
        if(!e.target.classList.contains('btn') || dif === 0) return;
        currentAngle += (Math.abs(dif) > 180) ? 
                        (Math.abs(dif) - 360)*Math.abs(dif)/dif : 
                        dif;
        house.style['-webkit-transform'] = 'rotateY(' + currentAngle + 'deg)';
        house.style['transform'] = 'rotateY(' + currentAngle + 'deg)';
    }, false); 
}());

Also, you can do a rotating 3D box with pure CSS. However, the > 180° rotation problem can only be solved with JavaScript.

pure CSS version of the demo

like image 145
Ana Avatar answered Sep 30 '22 12:09

Ana