小编典典

干净的方法来以编程方式使用JS的CSS过渡?

css

顾名思义,是否有适当的方法来设置一些初始CSS属性(或类),并告诉浏览器将其转换为另一个值?

var el = document.querySelector('div'),
    st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;

这不会激活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;

但是,这有点黑,据报道在某些android设备上不起作用。

建议使用,setTimeout以便浏览器有时间执行重绘,但是它也失败了,因为我们不知道重绘将花费多长时间。猜测适当的毫秒数(30-100?)以确保发生重绘就意味着牺牲性能,而不必要地闲置是希望浏览器在那短时间内表现出某种魔力。

通过测试,我发现了另一个解决方案,使用requestAnimationFrame在最新的Chrome上运行良好:

var el = document.querySelector('div'),
    st = el.style;
st.opacity = 0;
requestAnimationFrame(function() {
    st.transition = 'opacity 2s';
    st.opacity = 1;
});

我假设requestAnimationFrame等到下一次重画开始之前,然后执行回调,因此浏览器不会批处理属性更改。此处不确定,但可以在Chrome
29上正常使用。

更新: 经过进一步测试,该requestAnimationFrame方法在Firefox 23上效果不佳-
多数情况下似乎失败。

是否有合适的或推荐的(跨浏览器)方式来实现这一目标?


阅读 218

收藏
2020-05-16

共1个答案

小编典典

目前还没有一种干净的方法(不使用CSS动画-有关使用CSS动画的示例。有一个规范错误14617,很遗憾,自2011年提交以来就没有得到纠正。

setTimeout在Firefox中无法可靠地运行这是设计使然。

我不确定requestAnimationFrame-对原始问题的编辑说它也不可靠,但是我没有调查。(更新:看起来requestAnimationFrame至少一位Firefox核心开发人员认为是可以进行更多更改的地方,而不必一定看到先前更改的效果。)

window.getComputedStyle(elem).opacity;

请注意,仅运行getComputedStyle(elem)是不够的,因为它是惰性计算的。我相信您从getComputedStyle询问哪个属性都没有关系,重新样式仍然会发生。请注意,询问与几何相关的属性可能会导致更昂贵的回流。

2020-05-16