admin管理员组

文章数量:1026989

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 /

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';
}   

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/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';
}   
Share Improve this question edited Nov 25, 2012 at 8:59 synthet1c asked Nov 25, 2012 at 8:50 synthet1csynthet1c 6,2823 gold badges27 silver badges40 bronze badges 4
  • Despite your best efforts, this doesn't work in Opera. – beatgammit Commented Nov 25, 2012 at 8:54
  • I'm not too solid of a CSS guy, but from the looks of it, you're approach is a little weird. Right now you are changing the class of each individual face of the square AKA animating each face individually. it would be better to set up each face with the proper x,y,z chords, and then perform your animation on a container div (a.k.a. rotate them all on the same Y axis) - better because the you're just animating the solid object, not making each face of the object chase each other. – netpoetica Commented Nov 25, 2012 at 9:01
  • that's a good idea.. I'll give it a go now and post back with the results.. thanks keith – synthet1c Commented Nov 25, 2012 at 9:04
  • no luck unfortunately... it will happily rotate the z axis but y and x are not working.. the z axis only flips the box clockwise with the current face remaining.. – synthet1c Commented Nov 25, 2012 at 9:21
Add a ment  | 

1 Answer 1

Reset to default 7

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

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 /

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';
}   

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/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';
}   
Share Improve this question edited Nov 25, 2012 at 8:59 synthet1c asked Nov 25, 2012 at 8:50 synthet1csynthet1c 6,2823 gold badges27 silver badges40 bronze badges 4
  • Despite your best efforts, this doesn't work in Opera. – beatgammit Commented Nov 25, 2012 at 8:54
  • I'm not too solid of a CSS guy, but from the looks of it, you're approach is a little weird. Right now you are changing the class of each individual face of the square AKA animating each face individually. it would be better to set up each face with the proper x,y,z chords, and then perform your animation on a container div (a.k.a. rotate them all on the same Y axis) - better because the you're just animating the solid object, not making each face of the object chase each other. – netpoetica Commented Nov 25, 2012 at 9:01
  • that's a good idea.. I'll give it a go now and post back with the results.. thanks keith – synthet1c Commented Nov 25, 2012 at 9:04
  • no luck unfortunately... it will happily rotate the z axis but y and x are not working.. the z axis only flips the box clockwise with the current face remaining.. – synthet1c Commented Nov 25, 2012 at 9:21
Add a ment  | 

1 Answer 1

Reset to default 7

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

本文标签: creating a moving 3d box with CSS transitions and JavascriptStack Overflow