基于 Firefox 在这方面只是有 bug 的假设(见下面的分析),这是一个解决方法 https://jsfiddle.net/955k5fhh/7/适用于 Firefox。它包裹着#box
另一个元素中的元素div
,并且仅转换包装器。而且包装器一次只能从起点向一个方向旋转 90 度,因此 Firefox 不会把它搞砸。
过渡完成后,旋转将重置回起始位置,同时内框旋转到新位置,两者都没有过渡,因此更改不可见。
第二个重要的变化是使用当前计算的变换#box
并将旋转添加到其中,这样我们就不必在进行时跟踪旋转。
请注意,旋转的顺序很重要。为了实现您想要做的事情(在“世界空间”而不是“对象空间”中旋转),您需要以相反的顺序应用旋转。例如。要“向右”旋转,请使用.css("transform", "rotateY(90deg) " + currentComputedTransform)
。这将解决您在评论中提到的问题,该问题似乎围绕错误的轴旋转。请参阅下面的详细信息。
另请注意,如果已经有轮换正在进行,我不允许开始轮换,因为这是行不通的。如果您希望能够这样做,您可以将击键排队到数组中,但您可能还希望在这种情况下减少与队列长度成比例的转换持续时间,这样就不会永远花费时间。
更新的小提琴:https://jsfiddle.net/955k5fhh/7/ https://jsfiddle.net/955k5fhh/7/
相关JavaScript:
$("#box").wrap("<div id='outer'></div>");
var pending=null;
function rotate(axis,angle,dir) {
if (pending) return;
$("#outer").removeClass().addClass(dir);
var current=$("#box").css("transform");
if (current=='none') current='';
pending="rotate"+axis+"("+angle+"deg) "
+ current;
}
$("#outer").bind('transitionend', function() {
$(this).removeClass();
$("#box").css('transform',pending);
pending=null;
});
$('#up').bind('click', function() {
rotate('X',90,"up");
});
$('#down').bind('click', function() {
rotate('X',-90,"down");
});
$('#right').bind('click', function() {
rotate('Y',90,"right");
});
$('#left').bind('click', function() {
rotate('Y',-90,"left");
});
之前的分析
我一直在研究基于 JS 的解决方案,并且发现了这篇有用的文章https://gamedev.stackexchange.com/a/67317 https://gamedev.stackexchange.com/a/67317- 它指出要在“世界空间”而不是“对象空间”中旋转对象,只需颠倒旋转顺序即可。
基于此,我将您的小提琴简化为以下内容:
var rot = "";
var tr = "translateZ(-50px)";
$('#up').bind('click', function() {
rot=" rotateX(90deg)"+rot;
$("#box").css("transform",tr+rot);
});
$('#down').bind('click', function() {
rot=" rotateX(-90deg)"+rot;
$("#box").css("transform",tr+rot);
});
$('#right').bind('click', function() {
rot=" rotateY(90deg)"+rot;
$("#box").css("transform",tr+rot);
});
$('#left').bind('click', function() {
rot=" rotateY(-90deg)"+rot;
$("#box").css("transform",tr+rot);
});
https://jsfiddle.net/955k5fhh/ https://jsfiddle.net/955k5fhh/(请注意,这不是一个完整的解决方案,因为最终rot
字符串会变得太长)
在 Chrome 上,其行为符合预期。再一次,Firefox 会出错,即使你只是链接,例如的序列rotateX(90deg)
转变。
所以我更进一步,在同一轴上卷起相邻的旋转......
var rots = [];
var tr = "translateZ(-50px)";
function transform() {
var tf = "translateZ(-50px)";
rots.forEach(function(rot) {
tf += " rotate" + rot[0] + "(" + rot[1] + "deg)";
});
console.log(tf);
$("#box").css("transform", tf);
}
function addRot(axis,angle) {
if (rots.length==0 || rots[0][0]!=axis) {
rots.unshift([axis,angle]);
} else {
rots[0][1]+=angle;
}
transform();
}
$('#up').bind('click', function() {
addRot('X',90);
});
$('#down').bind('click', function() {
addRot('X',-90);
});
$('#right').bind('click', function() {
addRot('Y',90);
});
$('#left').bind('click', function() {
addRot('Y',-90);
});
https://jsfiddle.net/955k5fhh/2/ https://jsfiddle.net/955k5fhh/2/
同样,它在 Chrome 中运行良好,在 Firefox 中运行得更好一些,但一旦你切换轴,你可能会以错误的方式旋转。同样,如果您在转换完成之前单击按钮,它可能会以错误的方式旋转。
所以我得出的结论是,不幸的是,Firefox 在这方面确实存在缺陷,但至少有解决方法。