清洁的方式来编程使用CSS的CSS转换? [英] Clean way to programmatically use CSS transitions from JS?

查看:108
本文介绍了清洁的方式来编程使用CSS的CSS转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如标题所暗示的,是否有一种适当的方法来设置一些初始的CSS属性(或类),并告诉浏览器将这些值转换为另一个值?

As the title implies, is there a proper way to set some initial CSS properties (or class) and tell the browser to transition these to another value?

例如(小提琴):

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

这不会在Chrome 29 / Firefox 23中为元素的不透明度设置动画。 a href =http://blog.alexmaccaw.com/css-transitions =noreferrer>来源):

This will not animate the opacity of the element in Chrome 29/Firefox 23. This is because (source):


[...]你会发现,如果你应用两组属性,一个立即
在另一个之后,然后浏览器尝试优化属性
更改,忽略你的初始属性和防止转变。在后台,浏览器在绘制
之前批量化属性更改,虽然通常会加快渲染速度,但有时会影响

[...] you’ll find that if you apply both sets of properties, one immediately after the other, then the browser tries to optimize the property changes, ignoring your initial properties and preventing a transition. Behind the scenes, browsers batch up property changes before painting which, while usually speeding up rendering, can sometimes have adverse affects.

解决方案是在应用两组
属性之间强制重画。一个简单的方法是访问DOM
元素的 offsetHeight 属性[...]

The solution is to force a redraw between applying the two sets of properties. A simple method of doing this is just by accessing a DOM element’s offsetHeight property [...]

事实上,hack在当前的Chrome / Firefox版本中工作。更新后的代码(小提示 - 点击后打开

In fact, the hack does work in the current Chrome/Firefox versions. Updated code (fiddle - click Run after opening the fiddle to run animation again):

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

然而,这是相当黑的,据报道在一些Android设备上无法工作。

However, this is rather hackish and is reported to not work on some android devices.

另一个回答建议使用 setTimeout ,所以浏览器有时间执行重绘,但它也失败,因为我们不知道需要多长时间进行重绘。猜测一个体面的毫秒数(30-100?)以确保重绘发生意味着牺牲性能,不必要的空转希望浏览器在这一点上执行一些魔术。

Another answer suggests using setTimeout so the browser has time to perform a redraw, but it also fails in that we don't know how long it will take for a redraw to take place. Guessing a decent number of milliseconds (30-100?) to ensure that a redraw occurred means sacrificing performance, unnecessarily idling in the hopes that the browser performs some magic in that little while.

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

Through testing, I've found yet another solution which has been working great on latest Chrome, using requestAnimationFrame (fiddle):

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

我假设 requestAnimationFrame 在执行回调之前的下一个重绘的开始,因此浏览器不会批量更改属性。

I assume that requestAnimationFrame waits until right before the beginning of the next repaint before executing the callback, hence the browser does not batch up the property changes. Not entirely sure here, but works nicely on Chrome 29.

更新:在进一步测试后, requestAnimationFrame code>方法在Firefox 23上不能很好地工作 - 似乎大多数时间都失败。 (小提琴

Update: after further testing, the requestAnimationFrame method does not work very well on Firefox 23 - it seems to fail most of the time. (fiddle)

有正确的或者推荐(跨浏览器)的方式实现这个?

Is there a proper or recommended (cross-browser) way of achieving this?

推荐答案

目前还没有一个干净的方式CSS动画 - 请参阅 James Dinsdale的附近答案,了解使用CSS动画的示例)。有一个规范错误14617 ,没有收到太多

There isn't a clean way at this moment (without using CSS Animations -- see the nearby answer by James Dinsdale for an example using CSS Animations). There is a spec bug 14617, which didn't receive much traction since 2011.

setTimeout 在Firefox中无法可靠运行(这是按设计)。

setTimeout does not work reliably in Firefox (this is by design).

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

I'm not sure about requestAnimationFrame -- an edit to the original question says it doesn't work reliably either, but I did not investigate. (Update: it looks like requestAnimationFrame is considered at least by one Firefox core developer to be the place where you can make more changes, not necessarily see the effect of the previous changes.)

强制回流(例如通过访问 offsetHeight )是一种可能的解决方案,但是对于转换,它应该强制restyle(即 getComputedStyle https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/

Forcing reflow (e.g. by accessing offsetHeight) is a possible solution, but for transitions to work it should be enough to force restyle (i.e. getComputedStyle): https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/

window.getComputedStyle(elem).opacity;


$ b <是不够的,因为它是懒惰计算。我相信你从getComputedStyle请求哪个属性没有关系,restyle仍然会发生。请注意,要求与几何相关的属性仍然可能导致更昂贵的回流。

Note that just running getComputedStyle(elem) is not enough, since it's computed lazily. I believe it doesn't matter which property you ask from the getComputedStyle, the restyle will still happen. Note that asking for geometry-related properties still might cause a more expensive reflow.

有关reflow / restyle / repaint的更多信息: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/

More information on reflow/restyle/repaint: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/

这篇关于清洁的方式来编程使用CSS的CSS转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆