通过 JavaScript 分配时 CSS 转换不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8210560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CSS transitions do not work when assigned trough JavaScript
提问by Jon Koops
I'm having some major headache trying to apply CSS3 transitions to a slideshow trough JavaScript.
我在尝试通过 JavaScript 将 CSS3 转换应用于幻灯片放映时遇到了一些重大问题。
Basically the JavaScript gets all of the slides in the slideshow and applies CSS classes to the correct elements to give a nice animated effect, if there is no CSS3 transitions support it will just apply the styles without a transition.
基本上,JavaScript 获取幻灯片中的所有幻灯片,并将 CSS 类应用于正确的元素以提供漂亮的动画效果,如果没有 CSS3 过渡支持,它将只应用没有过渡的样式。
Now, my 'little' problem. All works as expected, all slides get the correct styles, the code runs without bugs (so far). But the specified transitions do not work, even though the correct styles where applied. Also, styles and transitions work when I apply them myself trough the inspector.
现在,我的“小”问题。一切都按预期工作,所有幻灯片都获得了正确的样式,代码运行没有错误(到目前为止)。但是即使应用了正确的样式,指定的过渡也不起作用。此外,当我通过检查器自己应用样式和过渡时,它们会起作用。
Since I couldn't find a logical explanation myself I thought someone here could answer it, pretty please?
由于我自己找不到合乎逻辑的解释,所以我认为这里有人可以回答,好吗?
I've put together a little example of what the code is right now: http://g2f.nl/38rvmaOr use JSfiddle (no images): http://jsfiddle.net/5RgGV/1/
我已经把代码现在的一个小例子放在一起:http: //g2f.nl/38rvma 或者使用 JSfiddle(无图像):http: //jsfiddle.net/5RgGV/1/
回答by ThinkingStiff
To make transition
work, three things have to happen.
为了transition
工作,必须发生三件事。
- the element has to have the property explicitly defined, in this case:
opacity: 0;
- the element must have the transition defined:
transition: opacity 2s;
- the new property must be set:
opacity: 1
- 元素必须明确定义属性,在这种情况下:
opacity: 0;
- 元素必须定义过渡:
transition: opacity 2s;
- 必须设置新属性:
opacity: 1
If you are assigning 1 and 2 dynamically, like you are in your example, there needs to be a delay before 3 so the browser can process the request. The reason it works when you are debugging it is that you are creating this delay by stepping through it, giving the browser time to process. Give a delay to assigning .target-fadein
:
如果您动态分配 1 和 2,就像您在示例中一样,则需要在 3 之前延迟,以便浏览器可以处理请求。它在您调试时起作用的原因是您通过逐步执行它来创建此延迟,从而为浏览器提供处理时间。延迟分配.target-fadein
:
window.setTimeout( function() { slides[targetIndex].className += " target-fadein"; }, 100 );
Or put .target-fadein-begin
into your HTML directly so it's parsed on load and will be ready for the transition.
或者.target-fadein-begin
直接放入您的 HTML 中,以便在加载时对其进行解析并准备好进行转换。
Adding transition
to an element is not what triggers the animation, changing the property does.
添加transition
到元素不会触发动画,更改属性会触发动画。
Demo: http://jsfiddle.net/ThinkingStiff/QNnnQ/
演示:http: //jsfiddle.net/ThinkingStiff/QNnnQ/
HTML:
HTML:
<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>
CSS:
CSS:
.fadeable {
opacity: 0;
}
.fade-in {
opacity: 1;
transition: opacity 2s;
-moz-transition: opacity 2s;
-ms-transition: opacity 2s;
-o-transition: opacity 2s;
-webkit-transition: opacity 2s;
}
Script:
脚本:
//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';
}, 100);
回答by transistor09
Trick the layout engine!
欺骗布局引擎!
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'
As already mentioned, transition
s work by interpolating from state Ato state B. If your script makes changes in the same function, layout engine cannot separate where state Aends and Bbegins. Unless you give it a hint.
如前所述,transition
s 通过从状态A插入到状态B 来工作。如果您的脚本在同一函数中进行了更改,则布局引擎无法将状态A结束和状态B开始的位置分开。除非你给它提示。
Since there is no officialway to make the hint, you must rely on side effects of some functions. In this case .offsetHeight
getter which implicitly makes the layout engine to stop, evaluate and calculate all properties that are set, and return a value. Typically, this should be avoided for performance implications, but in our case this is exactly what's needed: state consolidation.
由于官方没有给出提示的方法,所以必须依赖一些函数的副作用。在这种情况下,.offsetHeight
getter 隐式地使布局引擎停止、评估和计算所有设置的属性,并返回一个值。通常,出于性能影响,应该避免这种情况,但在我们的情况下,这正是所需要的:状态整合。
Cleanup code added for completeness.
为完整性添加了清理代码。
回答by user3723889
Some people have asked about why there is a delay. The standard wants to allow multiple transitions, known as a style change event, to happen at once (such as an element fading in at the same time it rotates into view). Unfortunately it does not define an explicit way to group which transitions you want to occur at the same time. Instead it lets the browsers arbitrarily choose which transitions occur at the same time by how far apart they are called. Most browsers seem to use their refresh rate to define this time.
有人问为什么会延迟。该标准希望允许同时发生多个转换,称为样式更改事件(例如,元素在旋转到视图的同时淡入)。不幸的是,它没有定义一种明确的方式来对您希望同时发生的转换进行分组。相反,它让浏览器可以通过调用相距多远来任意选择同时发生哪些转换。大多数浏览器似乎使用它们的刷新率来定义这个时间。
Here is the standard if you want more details: http://dev.w3.org/csswg/css-transitions/#starting
如果您想要更多详细信息,这里是标准:http: //dev.w3.org/csswg/css-transitions/#starting