我想制作一个3D矩形(平行六面体),用户可以用箭头移动。 它在Chrome中运行良好,但在Firefox中,一些转换(实际上很多)与Chrome不同。 看看这个小提琴(这是我的整个代码),并在两个浏览器中进行比较,以便更好地理解。

因为第一个小提琴包含很多代码,我会简化它并选择一个随机奇怪的过渡。 看看这个小提琴,然后按“向左”按钮或向左箭头一次。 它工作正常,但当你再次按下它时,矩形旋转3次而不是1次。

这是Firefox的错误还是我做错了什么?

下面的代码就是你在简化的小提琴中找到的代码。

 var position = 'show-front'; $('#left').bind('click', function() { if (position == 'show-front') { $('#box').removeClass().addClass('show-right'); position = 'show-right'; } else if (position == 'show-right') { $('#box').removeClass().addClass('show-back-3'); position = 'show-back-3'; } else if (position == 'show-back-3') { $('#box').removeClass().addClass('show-left'); position = 'show-left'; } else if (position == 'show-left') { $('#box').removeClass().addClass('show-front'); position = 'show-front'; } }); $(window).bind('keyup', function(event) { switch (event.keyCode) { case 37: // left $('#left').click(); break; } }); 
 .container { width: 150px; height: 100px; position: relative; margin: 25px auto 25px auto; perspective: 600px; } #box { width: 100%; height: 100%; position: absolute; transform-style: preserve-3d; transition: transform 1s; } #box figure { display: block; position: absolute; border: 1px solid black; line-height: 98px; font-size: 45px; text-align: center; font-weight: bold; color: white; } figure { margin: 0; } #box .front, #box .back { width: 148px; height: 98px; } #box .right, #box .left { width: 48px; height: 98px; left: 50px; } #box .top, #box .bottom { width: 148px; height: 48px; top: 25px; line-height: 48px; } #box .front { background: hsla(000, 100%, 50%, 0.7); } #box .back { background: hsla(160, 100%, 50%, 0.7); } #box .right { background: hsla(120, 100%, 50%, 0.7); } #box .left { background: hsla(180, 100%, 50%, 0.7); } #box .top { background: hsla(240, 100%, 50%, 0.7); } #box .bottom { background: hsla(300, 100%, 50%, 0.7); } #box .front { transform: translateZ(25px); } #box .back { transform: rotateX(180deg) translateZ(25px); } #box .right { transform: rotateY(90deg) translateZ(75px); } #box .left { transform: rotateY(-90deg) translateZ(75px); } #box .top { transform: rotateX(90deg) translateZ(50px); } #box .bottom { transform: rotateX(-90deg) translateZ(50px); } #box.show-front { transform: translateZ(-50px); } #box.show-right { transform: translateZ(-150px) rotateY(-90deg); } #box.show-back-3 { transform: translateZ(-50px) rotateX(180deg) rotateZ(-180deg); } #box.show-left { transform: translateZ(-150px) rotateY(90deg); } 
 <section class="container"> <div id="box" class="show-front"> <figure class="front">1</figure> <figure class="back">2</figure> <figure class="right">3</figure> <figure class="left">4</figure> <figure class="top">5</figure> <figure class="bottom">6</figure> </div> </section> 

===============>>#1 票数:3 已采纳

基于Firefox在这方面只是错误的假设(参见下面的分析), 这是一个适用于Firefox 的解决方法 它将#box元素包装在另一个div ,并且仅转换包装器。 并且包装器一次只能从一个方向从起点旋转90度,因此Firefox无法搞砸它。

转换完成后,旋转将重置回起始位置,同时内盒旋转到新位置,两者都没有过渡,因此变化不可见。

第二个重要的变化是使用#box的当前计算变换并将旋转添加到其中,这样我们就不必跟踪旋转。

请注意,旋转顺序很重要。 要实现您想要做的事情(在“世界空间”而不是“对象空间”中旋转),您需要以相反的顺序应用旋转。 例如,要“向右”旋转,请使用.css("transform", "rotateY(90deg) " + currentComputedTransform) 这将解决您在评论中提到的问题,它似乎围绕错误的轴旋转。 请参阅下面的详细信息。

另请注意,如果已经有一个轮换,我不允许轮换启动,因为这不起作用。 如果您希望能够在数组中排队,可以排队,但是在这种情况下,您可能还希望减少与队列长度成比例的转换持续时间,因此不需要永久。

更新小提琴: 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 - 它指出要在“世界空间”而不是“对象空间”中旋转对象,你只需要颠倒旋转的顺序。

基于此,我简化了你的小提琴:

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/ (请注意,这不是一个完整的解决方案,因为最终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/

再次,它在Chrome中运行良好,并且在Firefox中运行得更好,但是一旦你切换轴,你就可以以错误的方式旋转。 同样,如果在转换完成之前单击按钮,它可能会以错误的方式旋转。

所以我得出结论,不幸的是,Firefox在这方面只是错误,但至少有一些解决方法。

===============>>#2 票数:0

看起来你做的一切都很正确,Chrome与Firefox的轮换差异是由两个浏览器处理CSS3的方式引起的。 查看从show-back-4show-top-4的旋转时,CSS文件将旋转指定为270deg 在Firefox中,它就是这样做的。 在Chrome中,它看起来优化并且不会完全旋转,从而节省处理能力等。 所以是的,我认为这只是浏览器的一个区别,而不是其中任何一个的错误。

===============>>#3 票数:0

您可以尝试使用关键帧来获得对动画的更多控制,如下所示:

https://jsfiddle.net/L36v50kh/2/

我正在为小提琴中的所有过渡定义起点和终点,如下所示:

@keyframes front-to-right {
    from {transform: translateZ(-50px) rotateY(0deg); }
    to {transform:  translateZ(-150px) rotateY(-90deg);}
}

在两个浏览器中看起来都是一样的,但是在动画结束前单击按钮时会出现跳跃。

您也可以考虑使用JavaScript动画来获得精确控制并避免定义每个转换,如下所示:

 var applyRotation = function() { $('#box').css('transform', 'rotateY(' + rotateY + 'deg)'); handleMultipleRotations(); }; var unwindTimeout; var rotateY = 0; var handleMultipleRotations = function() { $('#box').css('transition-duration', ''); if (typeof unwindTimeout === 'number') { clearTimeout(unwindTimeout); unwindTimeout = undefined; } if (Math.abs(rotateY) >= 360) { unwindTimeout = setTimeout(function() { rotateY -= Math.floor(rotateY / 360) * 360; $('#box').css({ 'transition-duration': '0s', 'transform': 'rotateY(' + rotateY + 'deg)' }); }, 1000); } }; $('document').ready(function() { $('#left').on('click', function() { rotateY -= 90; applyRotation(); }); $('#right').on('click', function() { rotateY += 90; applyRotation(); }); }); 
 /* minified to draw focus to js */ .container{width:150px;height:100px;position:relative;margin:25px auto;perspective:600px}#box{width:100%;height:100%;position:absolute;transform-style:preserve-3d;transition:transform 1s}#box figure{display:block;position:absolute;border:1px solid #000;line-height:98px;font-size:45px;text-align:center;font-weight:700;color:#fff}figure{margin:0}#box .back,#box .front{width:148px;height:98px}#box .left,#box .right{width:48px;height:98px;left:50px}#box .bottom,#box .top{width:148px;height:48px;top:25px;line-height:48px}#box .front{background:hsla(000,100%,50%,.7)}#box .back{background:hsla(160,100%,50%,.7)}#box .right{background:hsla(120,100%,50%,.7)}#box .left{background:hsla(180,100%,50%,.7)}#box .top{background:hsla(240,100%,50%,.7)}#box .bottom{background:hsla(300,100%,50%,.7)}#box .front{transform:translateZ(25px)}#box .back{transform:rotateX(180deg) translateZ(25px)}#box .right{transform:rotateY(90deg) translateZ(75px)}#box .left{transform:rotateY(-90deg) translateZ(75px)}#box .top{transform:rotateX(90deg) translateZ(50px)}#box .bottom{transform:rotateX(-90deg) translateZ(50px)} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section class="container"> <div id="box" class="show-front"><figure class="front">1</figure><figure class="back">2</figure><figure class="right">3</figure><figure class="left">4</figure><figure class="top">5</figure><figure class="bottom">6</figure></div> </section> <section id="options"><p><button id="left">Left</button><button id="right">Right</button></p></section> 

  ask by Alin Ilici translate from so

未解决问题?本站智能推荐: