通过 JavaScript 分配时 CSS 转换不起作用

问题描述 投票:0回答:4

我在尝试通过 JavaScript 将 CSS3 过渡应用到幻灯片时遇到了一些大麻烦。

基本上,JavaScript 会获取幻灯片中的所有幻灯片,并将 CSS 类应用到正确的元素以提供漂亮的动画效果,如果没有 CSS3 过渡支持,它将仅应用样式而无需过渡。

现在,我的“小”问题。一切都按预期工作,所有幻灯片都获得正确的样式,代码运行没有错误(到目前为止)。但即使应用了正确的样式,指定的过渡也不起作用。此外,当我通过检查器自己应用样式和过渡时,它们会起作用。

由于我自己找不到合乎逻辑的解释,我想这里有人可以回答这个问题,好吗?

我整理了一个现在代码的小例子:http://g2f.nl/38rvma 或者使用 JSfiddle(无图像):http://jsfiddle.net/5RgGV/1/

javascript css css-transitions
4个回答
65
投票

要使

transition
发挥作用,必须发生三件事。

  1. 元素必须具有显式定义的属性,在本例中:
    opacity: 0;
  2. 元素必须定义转换:
    transition: opacity 2s;
  3. 必须设置新属性:
    opacity: 1

如果您动态分配 1 和 2,就像您在示例中一样,则需要在 3 之前有一个延迟,以便浏览器可以处理请求。当您调试它时它起作用的原因是您通过逐步执行它来创建这种延迟,从而给浏览器时间来处理。延迟分配

.target-fadein
:

window.setTimeout(function() {
  slides[targetIndex].className += " target-fadein";
}, 100); 

或者直接将

.target-fadein-begin
放入 HTML 中,以便在加载时对其进行解析并为转换做好准备。

向元素添加

transition
不会触发动画,更改属性才会触发动画。

// Works
document.getElementById('fade1').className += ' fade-in'

// Doesn't work
document.getElementById('fade2').className = 'fadeable'
document.getElementById('fade2').className += ' fade-in'

// Works
document.getElementById('fade3').className = 'fadeable'

window.setTimeout(function() {
  document.getElementById('fade3').className += ' fade-in'
}, 50)
.fadeable {
  opacity: 0;
}

.fade-in {
  opacity: 1;
  transition: opacity 2s;
}
<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>


16
投票

欺骗布局引擎!

function finalizeAndCleanUp (event) {
    if (event.propertyName == 'opacity') {
        this.style.opacity = '0'
        this.removeEventListener('transitionend', finalizeAndCleanUp)
    }
}
element.style.transition = 'opacity 1s'
element.style.opacity = '0'
element.addEventListener('transitionend', finalizeAndCleanUp)
// next line's important but there's no need to store the value
element.offsetHeight
element.style.opacity = '1'

如前所述,

transition
通过从状态A插值到状态B来工作。如果您的脚本在同一函数中进行更改,布局引擎无法分离状态 A 结束和 B 开始的位置。除非你给它一个提示。

由于没有官方的方式来做出提示,所以你必须依赖某些函数的副作用。在这种情况下,

.offsetHeight
getter 隐式地使布局引擎停止,评估和计算所有设置的属性,并返回一个值。通常,由于性能影响,应该避免这种情况,但在我们的例子中,这正是所需要的:状态整合。

为了完整性添加了清理代码。


4
投票

有人问为什么会延迟。该标准希望允许同时发生多个转换(称为样式更改事件)(例如元素在旋转到视图中的同时淡入)。不幸的是,它没有定义明确的方法来对您想要同时发生的转换进行分组。相反,它让浏览器可以根据调用的距离来任意选择同时发生哪些转换。大多数浏览器似乎使用刷新率来定义这个时间。

如果您想了解更多详细信息,这是标准: http://dev.w3.org/csswg/css-transitions/#starting


0
投票

transistor09的答案是正确的,应该被接受。然而,我更喜欢使用

element.offsetHeight
来确保在设置目标状态之前完全应用初始状态,而不是依赖
window.requestAnimationFrame
的模糊副作用:

// Set initial state
element.style.opacity = '0';
window.requestAnimationFrame(() => {
    // Delay the setting of the target state to the next animation frame.
    // The initial state has definitely been applied then.
    element.style.opacity = '1';
});
© www.soinside.com 2019 - 2024. All rights reserved.