Fab*_*tté 20 javascript css transition css3 css-transitions
正如标题所暗示的那样,是否有正确的方法来设置一些初始CSS属性(或类)并告诉浏览器将这些转换为另一个值?
例如(小提琴):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;
Run Code Online (Sandbox Code Playgroud)
这不会为Chrome 29/Firefox 23中元素的不透明度设置动画.这是因为(来源):
[...]你会发现,如果你同时应用两组属性,那么浏览器会尝试优化属性更改,忽略初始属性并阻止转换.在幕后,浏览器在绘制之前批量处理属性更改,虽然通常会加快渲染速度,但有时会产生不利影响.
解决方案是在应用两组属性之间强制重绘.这样做的一个简单方法就是访问DOM元素的
offsetHeight属性[...]
事实上,黑客确实可以在当前的Chrome/Firefox版本中运行.更新了代码(小提琴 - Run打开小提琴后点击再次运行动画):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
el.offsetHeight; //force a redraw
st.transition = 'opacity 2s';
st.opacity = 1;
Run Code Online (Sandbox Code Playgroud)
但是,这是相当hackish,并报告在某些Android设备上不起作用.
另一个答案建议使用,setTimeout以便浏览器有时间执行重绘,但它也失败了,因为我们不知道重绘需要多长时间.猜测一个相当大的毫秒数(30-100?)以确保重绘意味着牺牲性能,不必要地闲置,希望浏览器在那么短的时间内执行一些魔术.
通过测试,我发现了另一种解决方案,它在最新的Chrome上运行良好,使用requestAnimationFrame(小提琴):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
requestAnimationFrame(function() {
st.transition = 'opacity 2s';
st.opacity = 1;
});
Run Code Online (Sandbox Code Playgroud)
我假设requestAnimationFrame在执行回调之前等到下一次重绘开始之前,因此浏览器不会批量处理属性更改.这里不完全确定,但在Chrome 29上运行良好.
更新:经过进一步测试后,该requestAnimationFrame方法在Firefox 23上运行效果不佳 - 大多数时候似乎都失败了.(小提琴)
是否有适当的或推荐的(跨浏览器)方式来实现这一目标?
Nic*_*lay 11
目前还没有一种干净的方式(不使用CSS动画 - 请参阅James Dinsdale附近的答案,了解使用CSS动画的示例).有一个规范错误14617,遗憾的是自2011年提交以来没有采取行动.
setTimeout在Firefox中无法可靠地工作(这是设计使然).
我不确定requestAnimationFrame- 原始问题的编辑说它也不能可靠地工作,但我没有调查.(更新:看起来requestAnimationFrame 至少被一个Firefox核心开发人员认为是可以进行更多更改的地方,不一定能看到之前更改的效果.)
强制回流(例如通过访问offsetHeight)是一种可能的解决方案,但是为了使转换工作,它应该足以强制重新设置(即getComputedStyle):https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically- 创建-DOM元素/
window.getComputedStyle(elem).opacity;
Run Code Online (Sandbox Code Playgroud)
请注意,仅运行getComputedStyle(elem)是不够的,因为它是懒惰计算的.我相信你从getComputedStyle询问哪个属性并不重要,restyle仍然会发生.请注意,询问与几何相关的属性可能会导致更昂贵的回流.
关于reflow/restyle/repaint的更多信息:http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
情况自2013年以来发生了变化,所以这是一个新的答案:
您可以使用Web动画.它们在Chrome 36和Firefox 40 中原生实现,并且所有其他浏览器都有一个polyfill.
示例代码:
var player = snowFlake.animate([
{transform: 'translate(' + snowLeft + 'px, -100%)'},
{transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();
Run Code Online (Sandbox Code Playgroud)