我在尝试通过 JavaScript 将 CSS3 过渡应用到幻灯片时遇到了一些大麻烦。
基本上,JavaScript 会获取幻灯片中的所有幻灯片,并将 CSS 类应用到正确的元素以提供漂亮的动画效果,如果没有 CSS3 过渡支持,它将仅应用样式而无需过渡。
现在,我的“小”问题。一切都按预期工作,所有幻灯片都获得正确的样式,代码运行没有错误(到目前为止)。但即使应用了正确的样式,指定的过渡也不起作用。此外,当我通过检查器自己应用样式和过渡时,它们会起作用。
由于我自己找不到合乎逻辑的解释,我想这里有人可以回答这个问题,好吗?
我整理了一个现在代码的小例子:http://g2f.nl/38rvma 或者使用 JSfiddle(无图像):http://jsfiddle.net/5RgGV/1/
要使
transition
发挥作用,必须发生三件事。
opacity: 0;
transition: opacity 2s;
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>
欺骗布局引擎!
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 隐式地使布局引擎停止,评估和计算所有设置的属性,并返回一个值。通常,由于性能影响,应该避免这种情况,但在我们的例子中,这正是所需要的:状态整合。
为了完整性添加了清理代码。
有人问为什么会延迟。该标准希望允许同时发生多个转换(称为样式更改事件)(例如元素在旋转到视图中的同时淡入)。不幸的是,它没有定义明确的方法来对您想要同时发生的转换进行分组。相反,它让浏览器可以根据调用的距离来任意选择同时发生哪些转换。大多数浏览器似乎使用刷新率来定义这个时间。
如果您想了解更多详细信息,这是标准: http://dev.w3.org/csswg/css-transitions/#starting
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';
});