我有一个样式表,可以像这样设置一个css过渡属性(为了简洁省略了前缀版本):
transition: opacity 1s;
然后我在页面上有许多元素,我希望通过JavaScript修改每个元素的transition-delay
属性,以产生交错效果。我正在使用jQuery:
$(element).css('transition-delay', delay + 's');
但是,上面的代码不为元素添加内联transition-delay: Xs
。相反,它导致:
<div style="transition: Xs;">
但这很好,因为它按预期工作。不知何故,浏览器知道transition: Xs
真的意味着只需将transition-delay
设置为X并保持其余部分完整。
如果我现在通过$(element).attr('style')
获取该元素的内联样式,然后将其重新应用于元素$(element).attr('style', style)
,则HTML看起来完全相同,但现在转换完全覆盖了其他属性,并且实际上将元素的转换值设置为all Xs ease 0s
。
// HTML before - working
<div style="transition: Xs">
// then I do this
var style = $(el).attr('style');
$(el).attr('style', style);
// HTML after - broken!
<div style="transition: Xs">
正是我所描述的JSFiddle:http://jsfiddle.net/7vp8m/4/
答案 0 :(得分:5)
我认为只是写出问题并编写该演示真的帮助我找到答案:
style
属性不实际样式。我们需要使用CSSStyleDeclaration对象虽然似乎内联样式与style="..."
HTML属性中包含的内容一样简单(正如我所假设的),但事实证明并非如此。在幕后,内联样式(以及所有其他样式)实际上由名为CSSStyleDeclaration的对象定义。 style
属性中仅包含的字符串表示此对象,但不包含定义样式所需的所有信息。
这就是为什么设置`el.style =“width:100px;” 不工作。来自MDN article on HTMLElement.style:
除Opera中外,无法通过将字符串赋值给(只读)样式属性来设置样式,如elt.style =“color:blue;”。这是因为style属性返回CSSStyleDeclaration对象。相反,您可以设置样式属性,如下所示:
elt.style.color = "blue"; // Directly
var st = elt.style;
st.color = "blue"; // Indirectly
因此,这向我们展示了为什么$(el).attr('style', 'transition: Xs');
按预期工作 - 这正是我遇到的问题。这样做将修改底层的CSSStyleDeclaration对象,但并不总是按照我们想要的方式(因此我原来的问题)。
因此,解决方案是使用CSSStyleDeclaration提供的API。以下SO问题对我理解这个问题至关重要:JavaScript & copy style
var originalStyle = el.cloneNode().style;
这里我们使用的是cloneNode()方法,因为否则(如果我们得到el.style)CSSStyleDeclaration对象是通过引用复制的,这不是我想要的,因为我将更改元素的内联样式然后我想要以后恢复原始样式。首先克隆元素允许我们获得CSSStleDeclaration的“新”副本,当我们更改元素el
的内联样式时,它不会改变。
// first we need to delete all the style rules
// currently defined on the element
for (var i = el.style.length; i > 0; i--) {
var name = el.style[i];
el.style.removeProperty(name);
}
// now we loop through the original CSSStyleDeclaration
// object and set each property to its original value
for (var i = originalStyle.length; i > 0; i--) {
var name = originalStyle[i];
el.style.setProperty(name,
originalStyle.getPropertyValue(name),
priority = originalStyle.getPropertyPriority(name));
}
以下是我原始演示的更新,它实现了上述方法:http://jsfiddle.net/7vp8m/11/
答案 1 :(得分:0)
它打破了铬和新的&#34;歌剧,但没有在ff。在Maxthon中,它会在第一次停止并重新启动动画,然后运行良好。
正如你在http://jsfiddle.net/7vp8m/5所说的那样(幸运的是你解决了它),这是由于通过内联样式设置过渡延迟。
但是如果你强制引擎刷新css它会以某种方式工作(首先停止动画然后继续,播放动画更慢):http://jsfiddle.net/7vp8m/7/
function tick() {
[...]
$.each($('.test'), function(i, e){
e.style.marginLeft = x + 'px'; // Trying with vanilla js but it is the same
e.offsetHeight; // force the refresh. It moves again but bad
});
[...]
}
这也不起作用:http://jsfiddle.net/7vp8m/8/
$.each($('.test'), function (index, el) {
var style = $(el).attr('style');
style += '; transition-delay: '+delay + 's;'+
'-webkit-transition-delay'+delay + 's;'
$(el).attr('style', style);
delay += 0.2;
});
它似乎是一个与转换延迟相关的webkit错误,但是Maxthon以类似的方式停止了动画,因此它可能是一个更通用的错误。
所以,如果它是一个bug,最好的选择是不要通过js使用属性transition-delay。