Javascript 无法在同一调用堆栈中动态设置转换前的初始元素转换

Javascript 无法在同一调用堆栈中动态设置转换前的初始元素转换,javascript,css,Javascript,Css,如果我这样做: var div1 = document.getElementById('div1'), div2 = document.getElementById('div2'); function setAnimation() { div1.style.webkitTransform = 'matrix(1,0,0,1,1200,0)'; div2.style.webkitTransform = 'matrix(1,0,0,1,0,0)'; div1.sty

如果我这样做:

var div1 = document.getElementById('div1'),
    div2 = document.getElementById('div2');

function setAnimation() {
    div1.style.webkitTransform = 'matrix(1,0,0,1,1200,0)';
    div2.style.webkitTransform = 'matrix(1,0,0,1,0,0)';
    div1.style.webkitTransition = div2.style.webkitTransition = '-webkit-transform 2s ease';
}

function startAnimation() {
    div1.style.webkitTransform = 'matrix(1,0,0,1,0,0)';
    div2.style.webkitTransform = 'matrix(1,0,0,1,-1200,0)';
}

 setAnimation();
startAnimation();​
div2在屏幕外的动画效果很好,但是div1仍然保持在0,0的位置,并且从未看到任何变化

如果我完全删除startAnimation并将setAnimation更改为:

function setAnimation() {
    div1.style.webkitTransform = 'matrix(1,0,0,1,500,0)';
    div2.style.webkitTransform = 'matrix(1,0,0,1,-500,0)';
    div1.style.webkitTransition = div2.style.webkitTransition = '-webkit-transform 2s ease';
}
我会看到两个元素都从0,0开始设置动画到这些位置

看起来无法在与转换设置相同的调用堆栈中动态设置初始转换?或者,更清楚地说,如果转换和转换都设置在同一调用堆栈中,则转换将始终优先


这是为什么?

由于与每次回流相关的计算成本,大多数浏览器通过排队更改并成批执行更改来优化回流过程。在这种情况下,您将覆盖浏览器识别的图元的内联样式信息。浏览器将第一次更改和第二次更改排队,然后再最终决定是否应发生回流,这一过程一次完成。(将更改分为两个函数调用并不重要。)当尝试更新任何其他样式属性时,也会出现类似情况

您始终可以使用以下任意一种方法强制浏览器回流:

  • 斜视,斜视,斜视,斜视
  • scrollTop、scrollLeft、scrollWidth、scrollHeight
  • clientTop、clientLeft、clientWidth、clientHeight
  • getComputedStyle()(IE中的currentStyle)
因此,只需将第一个函数更改为:

var computedStyles = [];

function setAnimation() {
    div1.style.webkitTransform = 'matrix(1,0,0,1,1200,0)';
    div2.style.webkitTransform = 'matrix(1,0,0,1,0,0)';

    // force div's 1 and 2 to reflow
    computedStyles[div1] = div1.clientHeight;
    computedStyles[div2] = div2.clientHeight;
}
现在浏览器将执行初始转换。您不需要两个函数来完成这一点,只需在两者之间强制回流即可


由于在尝试解决像这样的回流/重绘问题时可能会出现一些令人头痛的问题,我始终建议使用CSS动画,即使您必须使用CSSOM从样式表中动态创建和删除样式规则。阅读这里的更多内容:

我认为一种解决方案是在很短的setTimeout内调用第二个函数,尽管您的问题更多的是为什么会发生这种情况,而不是如何解决。我也想知道解决这个问题的最佳实践方案。是的,这就是我目前解决这个问题的方法。感觉很脏。哇,非常感谢。这是一直困扰我的事情之一。不过,我还有一个问题:为什么将过渡设置为settimeout(即使延迟最小)会迫使浏览器回流?我不确定,因为我不是一个浏览器开发人员,但我最好的猜测是,浏览器试图在何时回流上保持智能。如果它有回流更改排队,然后将出现一个timout,则需要这段时间来回流页面(因为它无论如何都会等待)。我认为超时本身就是触发器,这就是为什么它可以延迟1毫秒甚至0毫秒并不重要。setTimeout在这方面已经取得了很多成功,我只是不确定它是否像我列出的其他方法一样普遍适用于跨浏览器。