使用CSS过渡和Javascript创建一个可移动的3D盒子

5
我一直在使用CSS尝试创建一个3D盒子,你可以使用纯JavaScript选择面。
它只是改变盒子div的className,并使用transition属性在位置之间平滑过渡。
这里有一个jsfiddle展示了一个工作示例 http://jsfiddle.net/synthet1c/VdDmA/1/ 目前看起来很酷,但它并不完全按照我想要的方式运行... 有人知道如何在过渡时保持盒子的稳定吗?当前,如果面从360度旋转到90度,则面将以错误方向旋转270度。我知道为什么会这样做,但无法找到解决方法。
我已经添加了所有浏览器前缀,但只在Firefox上使用过。
感谢任何建议,

安德鲁 #right, #back, #left, #front { 高度:150像素; 宽度:150像素; 位置:绝对; 边框:1像素实心 rgba(200,200,200,0.7); 背景颜色:半透明蓝色(rgba(0,0,255,0.5)); 外边距:0像素; }

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

尽管你已经尽力了,但这在Opera中无法正常工作。 - beatgammit
我不是很擅长CSS,但从外观来看,你的方法有点奇怪。现在你正在改变正方形每个面的类别,也就是单独地对每个面进行动画处理。更好的方法是为每个面设置正确的x、y、z坐标,然后在容器div上执行动画(即将它们全部绕同一Y轴旋转)- 更好的原因是你只是在对实体对象进行动画处理,而不是让对象的每个面相互追逐。 - netpoetica
那是个好主意。我现在会尝试并发布结果。谢谢Keith。 - synthet1c
很遗憾,它只能愉快地旋转Z轴,但Y和X无法工作。当前面保持不变时,Z轴只会顺时针翻转盒子。 - synthet1c
1个回答

6

其实很简单。你只需要检查当前角度和你想要达到的角度之间绝对值的差,我们叫它 dif,如果这个差超过了 180°,那么你就应该旋转 360° 减去 dif 的绝对值,旋转方向取决于 dif 的符号。

我还对 CSS 进行了一些修改,如果你想更好地了解如何创建逼真的立方体,你可以查看我对类似问题的详细回答

演示

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>

相关的 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); 
}());

同时,您可以使用纯 CSS 完成一个旋转的 3D 盒子。然而,将其旋转超过 180° 的问题只能通过 JavaScript 解决。

演示的纯 CSS 版本


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接