控制CSS立方体旋转(变换)并从3d矩阵中提取值

我使用上/下和左/右键旋转的CSS立方体,但是我在旋转方向上有问题.

尝试#1

DEMO

使用this article我设法绑定键并将旋转应用于多维数据集.我的第一个问题是CSS变换函数旋转元素轴,所以当,即.我按下,Y和Z轴更换位置.我调整了这种情况下的原始代码,但另一个问题是,由于轴是向量,当我按下2次X和Z回到原位,但向量被反转(左键开始向右旋转立方体,反之亦然)所以现在我必须旋转立方体相反的方向,以获得所需的结果,我不知道如何检测轮轴是倒置的.

JavaScript的

var xAngle = 0,yAngle = 0,zAngle = 0,cube = $("#cube");

$(document).keydown(function(e) { //keyup maybe better?

  e.preventDefault();

  var key = e.which,arrow = {left: 37,up: 38,right: 39,down: 40},x = xAngle/90,y = yAngle/90;

    switch(key) {
      case arrow.left:
        if (x%2 == 0)
          yAngle -= 90;
        else
          zAngle += 90;
      break;
      case arrow.up:
        if (y%2 == 0)
          xAngle += 90;
        else
          zAngle -= 90;
      break;
      case arrow.right:
        if (x%2 == 0)
          yAngle += 90;
        else
          zAngle -=90;
      break;
      case arrow.down:
        if (y%2 == 0)
          xAngle -= 90;
        else
          zAngle += 90;
      break;
    }

    var rotate = "rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg) rotateZ(" + zAngle + "deg)";
    cube.css({"transform":rotate});  

});

尝试#2

DEMO

我使用this article方法制作了另一个版本,试图通过分解和更新css 3d矩阵来解决同样的问题,但是还有其他问题.反复按箭头随机方向立方体改变观察角度(多于一侧可见).

当我可以从3d矩阵获得旋转值或向量方向,但是没有solutions I found似乎可以工作,这将是巨大的.我猜,因为3D矩阵是通过将来自所有传递的函数(rotateX,rotateY和translateZ)的值相乘得出的,而且那种数学方法可以超出我的头脑.

JavaScript的

var Vector = function(x,y,z) {
    this.x = x;
    this.y = y;
    this.z = z;
}

WebKitCSSMatrix.prototype.transformVector = function(v) {
    var xOut = this.m11*v.x + this.m12*v.y + this.m13*v.z;
    var yOut = this.m21*v.x + this.m22*v.y + this.m23*v.z;
    var zOut = this.m31*v.x + this.m32*v.y + this.m33*v.z;

    return new Vector(xOut,yOut,zOut);
};

function applyRotation(vector,angle) {

    var cube = $('#cube');

    var matrix = new WebKitCSSMatrix(cube.css('webkitTransform'));

    var vector = matrix.transformVector(vector);

    var newMatrix = matrix.rotateAxisAngle(vector.x,vector.y,vector.z,angle);

    cube.get(0).style.webkitTransform = newMatrix;
}

// rotate using arrow keys
$(document).keyup(function(e) {

    e.preventDefault();

    var key = e.which,v,a;

        switch(key) {
            case arrow.left:
                v = new Vector(0,1,0),a = -90;
            break;

            case arrow.right:
                v = new Vector(0,a = 90;
            break;

            case arrow.up:
                v = new Vector(1,a = 90;
            break;

            case arrow.down:
                v = new Vector(1,a = -90;
            break;
        }

        applyRotation(v,a);

});

尝试#3

DEMO

第三个版本我单独旋转,旋转后改变类,所以我总是只是旋转X和Y在正确的方向,但是当旋转发生时,立方体被分解,我认为上下旋转是错误的(加代码有点blo肿和丑陋).对于不支持preserve-3d属性的浏览器,这种方法的另一方面是跨浏览器兼容性更大.

JavaScript的

$(document).keyup(function(e) {

  e.preventDefault();

  var key = e.which,front = "rotateX(0deg) translateZ(100px)",back = "rotateX(180deg) translateZ(100px)",right = "rotateY(90deg) translateZ(100px)",left = "rotateY(-90deg) translateZ(100px)",top = "rotateX(90deg) translateZ(100px)",bottom = "rotateX(-90deg) translateZ(100px)";

    switch(key) {
      case arrow.left:
        $(".front").css({"transform":left});
        $(".back").css({"transform":right});
        $(".left").css({"transform":back});
        $(".right").css({"transform":front});
        var front = $(".front");
        var back = $(".back");
        var left = $(".left");
        var right = $(".right");
        front.removeClass("front").addClass("left");
        back.removeClass("back").addClass("right");
        right.removeClass("right").addClass("front");
        left.removeClass("left").addClass("back");
      break;
      case arrow.up:
        $(".front").css({"transform":top});
        $(".back").css({"transform":bottom});
        $(".top").css({"transform":back});
        $(".bottom").css({"transform":front});
        var front = $(".front");
        var back = $(".back");
        var top = $(".top");
        var bottom = $(".bottom");
        front.removeClass("front").addClass("top");
        back.removeClass("back").addClass("bottom");
        top.removeClass("top").addClass("back");
        bottom.removeClass("bottom").addClass("front");
      break;
      case arrow.right:
        $(".front").css({"transform":right});
        $(".back").css({"transform":left});
        $(".left").css({"transform":front});
        $(".right").css({"transform":back});
        var front = $(".front");
        var back = $(".back");
        var left = $(".left");
        var right = $(".right");
        front.removeClass("front").addClass("right");
        back.removeClass("back").addClass("left");
        right.removeClass("right").addClass("back");
        left.removeClass("left").addClass("front");
      break;
      case arrow.down:
        $(".front").css({"transform":bottom});
        $(".back").css({"transform":top});
        $(".top").css({"transform":front});
        $(".bottom").css({"transform":back});
        var front = $(".front");
        var back = $(".back");
        var top = $(".top");
        var bottom = $(".bottom");
        front.removeClass("front").addClass("bottom");
        back.removeClass("back").addClass("top");
        top.removeClass("top").addClass("front");
        bottom.removeClass("bottom").addClass("back");
      break;
    }

});

参考资料:

> Creating basic CSS cube
> MDN docs on transform property
> W3.org documentation on 3D transforms
> 3dmatrix documentation
> webkitCSSMatrix documentation

解决方法

尝试2的问题是rotateAxisAngle以所需的相反顺序执行矩阵乘法.而且,更糟糕的是,班级没有任何功能按照你想要的顺序进行乘法运算.

作为一种替代方式,我选择使用浏览器本身来做数学.
我创建一个将被隐藏的div,我将在哪里应用转换来获取新的矩阵.

使用这种方法,javascript变得更短:

function applyTransform (transform) {

    var cubeCalculator = $('.cubecalculator');
    var cube = $('#cube');

    var matrix = cubeCalculator.css('webkitTransform');
    var composite = transform + ' ' + matrix;
    cubeCalculator.get(0).style.webkitTransform = composite;

    matrix = cubeCalculator.css('webkitTransform');
    cube.get(0).style.webkitTransform = matrix;
}

// rotate using arrow keys
$(document).keyup(function(e) {

    e.preventDefault();

    var key = e.which,t;

    switch(key) {
        case arrow.left:
            t = 'rotateY(-90deg)';
        break;

        case arrow.right:
            t = 'rotateY(90deg)';
        break;

        case arrow.up:
            t = 'rotateX(90deg)';
        break;

        case arrow.down:
            t = 'rotateX(-90deg)';
        break;
    }

    applyTransform (t);

});

我认为代码是非常自明的:我将转换应用到元素作为新变换和当前变换的组合(您不需要从矩阵中提取值,可以按原样应用)

demo

(我不知道为什么,它没有在codepen工作,已经把它移动到…)

最后我得到了* Firefox的行为!

function applyTransform (transform1,transform2) {
    var matrix,composite1,composite2;
    var cubeCalculator = $('.cubecalculator');
    var cube = $('#cube');

    matrix = cubeCalculator.css('transform');
    composite1 = transform1 + ' ' + matrix;
    composite2 = transform2 + ' ' + matrix;
    cubeCalculator.get(0).style.transform = composite2;
    cube.get(0).style.transition = 'none';
    cube.get(0).style.transform = composite1;

    window.setTimeout (function() {
        cube.get(0).style.transform = composite2;
        cube.get(0).style.transition = 'transform 1s';
    },10   );
}

// rotate using arrow keys
$(document).keyup(function(e) {

    e.preventDefault();

    var key = e.which,t1,t2;

    switch(key) {
        case arrow.left:
            t1 = 'rotateY(0deg)';
            t2 = 'rotateY(-90deg)';
        break;

        case arrow.right:
            t1 = 'rotateY(0deg)';
            t2 = 'rotateY(90deg)';
        break;

        case arrow.up:
            t1 = 'rotateX(0deg)';
            t2 = 'rotateX(90deg)';
        break;

        case arrow.down:
            t1 = 'rotateX(0deg)';
            t2 = 'rotateX(-90deg)';
        break;
    }

    applyTransform (t1,t2);

});

一些更复杂的代码,但使浏览器完全清楚你想要做什么…只要你等到过渡结束,工作正常.

相关文章

Css3如何实现鼠标移上变长特效?(图文+视频)
css3怎么实现鼠标悬停图片时缓慢变大效果?(图文+视频)
jquery如何实现点击网页回到顶部效果?(图文+视频)
css3边框阴影效果怎么做?(图文+视频)
css怎么实现圆角边框和圆形效果?(图文+视频教程)
Css3如何实现旋转移动动画特效