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

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

问题描述



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



例如(小提琴):

  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>来源):


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



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


事实上,hack在当前的Chrome / Firefox版本中工作。更新后的代码(小提琴) - 点击打开小提琴后运行再次):

  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 小提示):



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

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



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



是否有适当的或推荐的浏览器)实现这种方式?

解决方案

目前还没有一个干净的方式 James Dinsdale附近的答案有关使用CSS动画的示例)。有一个规范错误14617 ,自2011年以来没有受到太多的关注。 / p>

setTimeout 在Firefox中无法可靠运作()。



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



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

  window.getComputedStyle(elem).opacity;注意,只是运行 getComputedStyle(elem) 


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



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


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?

For example (fiddle):

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

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.

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 [...]

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;

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

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.

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;
});

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.

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?

解决方案

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 does not work reliably in Firefox (this is by design).

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.)

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;

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.

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

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

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