CSS3转换Matrix3D动画故障,为什么?

时间:2014-11-28 00:43:00

标签: javascript css3 matrix 3d rotational-matrices

我已经在this fiddle中运行了它。我试图让一个立方体的两个面旋转,但是当它们在z轴上相互通过时,彼此前面的跳跃。我想要的只是在浏览器中学习Matrix 3D变换的基础知识。

我应该补充一点,我知道它是z轴交叉,但问题是,DOM对象是否可以沿着z-azis传播它?它似乎只能为整个对象提供一个z位置

我可能有错误的矩阵计算,我当然是3D图形菜鸟,但我认为事情不能太远,因为除了显而易见的问题之外,行为几乎与预期一致。

奖励积分:

我的z轴旋转矩阵表现不像我预期的那样。我不确定为什么。 X和Y的工作,如果你也可以帮助这个,那就太棒了。

守则:

HTML:

<div id="world" style="width: 400px, height: 400px">
    <div class="face" id="test" style="background-color: red;"></div>
    <div class="face" id="test2" style="background-color: pink;"></div>    
</div>

CSS:

#world {
    perspective: 100;
    perspective-origin:200px 200px;
    transform-style: preserve-3d;
}

.face{
    position: absolute;
    opacity: 0.9;
    top: 150px;
    left: 150px;
    width: 100px;
    height: 100px;
}

JS:

DEG_TO_RAD = 0.017453292519943295;

function MatrixEl (el) {
    this.el = el;
    this.matrix = this.getMatrix();
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.xrot = 0;
    this.yrot = 0;
    this.zrot = 0;
    this.current_scale = 1;
}

MatrixEl.prototype.getMatrix = function () {
    return [
    [1,0,0,0],
    [0,1,0,0],
    [0,0,1,0],
    [0,0,0,1],
    ];
};

MatrixEl.prototype.scale = function (scale) {
    this.current_scale = scale;
    this.matrix[0][0] *= scale;
    this.matrix[1][1] *= scale;
    this.matrix[2][2] *= scale;
};

MatrixEl.prototype.translate = function (x, y, z) {
    m = this.matrix;
    this.x = x;
    this.y = y;
    this.z = z;
    m[3][0] = this.x;
    m[3][1] = this.y;
    m[3][2] = this.z;
}

MatrixEl.prototype.rotate = function (x, y, z) {
    var m = this.matrix;
    this.xrot = x;
    this.yrot = y;
    this.zrot = z;
    var amount = this.xrot * DEG_TO_RAD;
    m[1][1] *= Math.cos(amount);
    m[1][2] *= Math.sin(-amount);
    m[2][1] *= Math.sin(amount);
    m[2][2] *= Math.cos(amount);    

    var amount = this.yrot * DEG_TO_RAD;
    m[0][0] *= Math.cos(amount);
    m[0][2] *= Math.sin(amount);
    m[2][0] *= Math.sin(-amount);
    m[2][2] *= Math.cos(amount);    

    var amount = this.zrot * DEG_TO_RAD;
    m[0][0] *= Math.cos(amount);
    m[0][1] *= Math.sin(-amount);
    m[1][0] *= Math.sin(amount);
    m[1][1] *= Math.cos(amount);
};

MatrixEl.prototype.set = function (x, y, z, xrot, yrot, zrot, scale) {
    var m = this.matrix = this.getMatrix();
    this.rotate(xrot, yrot, zrot);
    this.scale(scale);
    this.translate(x, y, z);
    this.el.style.transform="matrix3d(" + m[0].concat(
            m[1],
            m[2],
            m[3]
        ).join(',') + ')';
};
var yRotVel = 45 / 1000;
var dist = 50;
var time = 0
var square = new MatrixEl(document.getElementById('test'));
var square2 = new MatrixEl(document.getElementById('test2'));

function animate (dt) {
    var angle = dt*yRotVel;
    var z = dist*Math.sin(dt*yRotVel*DEG_TO_RAD);
    var z2 = dist*Math.sin((dt*yRotVel+ 90)*DEG_TO_RAD);

    // square.set(x, y, z, xrot, yrot, zrot, scale)
    square.set(0, z, z, angle, 0, 0, 1.0);
    square2.set(0, z2, z2, angle+90, 0, 0, 1);
    requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

1 个答案:

答案 0 :(得分:0)

此修复程序位于this fiddle,我的问题是浏览器无法轻松完成各个项目的动画。

为了解决这个问题,我简单地构建了一个立方体,然后对整个立方体进行了动画处理,而不是为各个面设置动画效果。它有效。

矩阵/矢量数学需要正确完成,就像你现在组合旋转一样,它以不应该的方式扭曲对象。我很快就会尝试修复这部分代码,但是在回答原来的问题时,你可以毫无故障地做到这一点。这些故障是由于整体形状没有动画造成的。

以下代码包含更改的方法:

var yRotVel = 45 / 1000;
var dist = 50;
var time = 0
var square = new MatrixEl(document.getElementById('test'));
var square2 = new MatrixEl(document.getElementById('test2'));
var square3 = new MatrixEl(document.getElementById('test3'));
var square4 = new MatrixEl(document.getElementById('test4'));
var square5 = new MatrixEl(document.getElementById('test5'));
var square6 = new MatrixEl(document.getElementById('test6'));
var cube = new MatrixEl(document.getElementById('world'));

square.set(150, 150, 50, 0, 0, 0, 1.0);
square2.set(150, 100, 0, 90, 0, 0, 1);
square3.set(150, 150, -50, 180, 0, 0, 1);
square4.set(150, 200, 0, 270, 0, 0, 1);
square5.set(100, 150, 0, 0, 90, 0, 1);
square6.set(200, 150, 0, 0, 90, 0, 1);

function animate (dt) {
    var angle = dt*yRotVel;
    var z = dist*Math.sin(dt*yRotVel*DEG_TO_RAD);
    // square.set(x, y, z, xrot, yrot, zrot, scale)
    cube.set(0, 0, 0, 0, angle, 0, 1);
    requestAnimationFrame(animate);
}
requestAnimationFrame(animate);