我制作了CSS立方体,我正在使用上/下和左/右键旋转,但我在旋转方向上遇到了问题。
使用this article我设法绑定密钥并将旋转应用于多维数据集。我的第一个问题是CSS transform
函数旋转元素轴所以,即。我按下,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});
});
我使用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,
arrow = {left: 37, up: 38, right: 39, down: 40},
v,
a;
switch(key) {
case arrow.left:
v = new Vector(0,1,0),
a = -90;
break;
case arrow.right:
v = new Vector(0,1,0),
a = 90;
break;
case arrow.up:
v = new Vector(1,0,0),
a = 90;
break;
case arrow.down:
v = new Vector(1,0,0),
a = -90;
break;
}
applyRotation(v, a);
});
我制作的第三个版本单独旋转并在旋转后更改类,所以我总是只是向右旋转X和Y,但是当旋转发生时,立方体会被分解,我认为上下旋转是错误的(加上代码是有点的臃肿和丑陋)。对于不支持preserve-3d
属性的浏览器,这种方法的另一方面是更大的跨浏览器兼容性。
的JavaScript
$(document).keyup(function(e) {
e.preventDefault();
var key = e.which,
arrow = {left: 37, up: 38, right: 39, down: 40},
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;
}
});
参考资料:
答案 0 :(得分:2)
尝试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,
arrow = {left: 37, up: 38, right: 39, down: 40},
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);
});
我认为代码非常自我解释:我将变换应用于元素作为新变换和当前变换的组合(您不需要从矩阵中提取值,可以按原样应用)
(我不知道为什么,它在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,
arrow = {left: 37, up: 38, right: 39, down: 40},
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);
});
稍微复杂的代码,但是让浏览器完全清楚你想要它做什么... 只要等到转换结束,就可以正常工作。
答案 1 :(得分:0)
演示2几乎就在那里。您的问题是您正在使用多维数据集的中间动画状态来计算新位置:
var matrix = new WebKitCSSMatrix(cube.css('webkitTransform'));
相反,您应该存储和更新内部目标矩阵:
此外,似乎这段代码:
var vector = matrix.transformVector(vector);
var newMatrix = matrix.rotateAxisAngle(vector.x, vector.y, vector.z, angle);
不按预期工作。这就是你想要的:
var newMatrix = new WebKitCSSMatrix().rotateAxisAngle(...).multiply(matrix)