使用JavaScript设置CSS动画延迟

7
我在CSS文件中有一些关键帧动画。已经指定了animation-delay。 包装器div具有data-delay属性。
我想获取CSS文件中的animation-delay,并将data-delay的值添加到其中。 然后,我希望动画以新延迟开始。
我尝试过ele[i].style.animationDelay。 但是这似乎返回null,直到我给它设置一个值为止。
如果我设置ele[i].style.animationDelay ='5s',动画仍以CSS文件中的延迟运行。
HTML
<div id="wrapper" data-delay="2s" >
    <h1 id="hi">Hi</h1>
    <h1 id="name">test!</h1>
</div>

CSS

body { font-size: 300%; }

#wrapper h1 { position: absolute; }

#hi {
    transform: translate(-200px, 100px);

    animation-name: hi;
    animation-duration: .5s;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    animation-delay: 0s;
}

#name {
    transform: translate(-200px, 150px);

    animation-name: name;
    animation-duration: .5s;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    animation-delay: 1s;
}

@keyframes hi{
    100% { transform: translate(50px, 100px) };
}

@keyframes name{
    100% { transform: translate(50px, 150px) };
}

JS

var wrapper = document.getElementById('wrapper');
var ele = wrapper.children;
var delay = wrapper.getAttribute('data-delay');

for (var i=0;i<ele.length;i++) {

    alert(ele[i].style.animationDelay);
    ele[i].style.animationDelay = delay;
    alert(ele[i].style.animationDelay);
}

http://jsfiddle.net/FHuKN/4/


1
你需要在所有这些属性前加上前缀 :/ (例如“-moz-animation-name”,“.style.mozAnimationDelay”等)。 - joequincy
使用前缀,这对我起作用:http://jsfiddle.net/FHuKN/5/。但请注意,带前缀属性的驼峰命名版本以大写字母开头。 - pimvdb
http://jsfiddle.net/FHuKN/6/ - joequincy
2个回答

6

我只在 Mac 10.8 Chrome 25、Safari 6.0 和 FF 18.0 上进行过测试。

听起来你想要做的主要事情是将 data-delay 值添加到已经应用于元素的现有动画延迟中。

HTML - 保持不变

<div id="wrapper" data-delay="5.1s" >
    <h1 id="hi">Hi</h1>
    <h1 id="name">test!</h1>
</div>

CSS - 厂商前缀和初始关键帧(0%)已添加。

body { font-size: 300%; }

#wrapper h1 { position: absolute; }

#hi { 
    -webkit-transform: translate(-200px, 100px);
    -webkit-animation-name: hi;
    -webkit-animation-duration: .5s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-fill-mode: forwards;
    -webkit-animation-delay: 2.1s;

    -moz-transform: translate(-200px, 100px);
    -moz-animation-name: hi;
    -moz-animation-duration: .5s;
    -moz-animation-timing-function: linear;
    -moz-animation-fill-mode: forwards;
    -moz-animation-delay: 2.1s;

    transform: translate(-200px, 100px);
    animation-name: hi;
    animation-duration: .5s;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    animation-delay: 2.1s;
}

#name { 
    -webkit-transform: translate(-200px, 150px);
    -webkit-animation-name: name;
    -webkit-animation-duration: .5s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-fill-mode: forwards;
    -webkit-animation-delay: 3.1s;

    -moz-transform: translate(-200px, 150px);
    -moz-animation-name: name;
    -moz-animation-duration: .5s;
    -moz-animation-timing-function: linear;
    -moz-animation-fill-mode: forwards;
    -moz-animation-delay: 3.1s;

    transform: translate(-200px, 150px);
    animation-name: name;
    animation-duration: .5s;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    animation-delay: 3.1s;
}

@-moz-keyframes hi{
    0% { -moz-transform: translate(-200px, 100px); }
    100% { -moz-transform: translate(50px, 100px); }
}
@-webkit-keyframes hi {
    0% { -webkit-transform: translate(-200px, 100px); }
    100% { -webkit-transform: translate(50px, 100px); }
}
@keyframes hi{
    0% { transform: translate(-200px, 100px); }
    100% { transform: translate(50px, 100px); }
}

@-moz-keyframes name {
    0% { -moz-transform: translate(-200px, 150px); }
    100% { -moz-transform: translate(50px, 150px); }
}
@-webkit-keyframes name {
    0% { -webkit-transform: translate(-200px, 150px); }
    100% { -webkit-transform: translate(50px, 150px); }
}
@keyframes name {
    0% { transform: translate(-200px, 150px); }
    100% { transform: translate(50px, 150px); }
}

JAVASCRIPT

在一个元素上,style属性并不能包含所有的样式信息,因为它仅代表通过style属性直接设置在元素上的样式。 MDN

window.getComputedStyle()似乎很好用。

处理前缀属性有点麻烦,但是在我测试的浏览器中都可以正常工作。

(function(undefined) {

    var wrapper = document.getElementById('wrapper'),
        elms = wrapper.children,
        delay = wrapper.getAttribute('data-delay'),
        prop,
        styl,
        cur,
        i;

    delay = !delay ? 0 : Number(delay.replace(/[^\d\.]/g, ''));

    if (!elms.length) {
        return;
    }

    styl = window.getComputedStyle(elms[0]);

    if (styl.getPropertyValue('animation-delay')) {
        prop = 'animation-delay';

    } else if (styl.getPropertyValue('-webkit-animation-delay')) {
        prop = '-webkit-animation-delay';

    } else if (styl.getPropertyValue('-moz-animation-delay')) {
        prop = '-moz-animation-delay';

    } else {
        console.log('unable to find prop');
        return;
    }
    // console.log('prop', prop);

    for (i = 0; i < elms.length; i++) {
        styl = window.getComputedStyle(elms[i]);
        cur = styl.getPropertyValue(prop);
        cur = Number(cur.replace(/[^\d\.]/g, ''));
        elms[i].style.setProperty(prop, (cur + delay) + 's');

        console.log('delay: ' + cur + 's -> ' + (cur + delay) + 's')
    }

})();

http://jsfiddle.net/FHuKN/11/


今天在Firefox中测试了它。有人能解释一下为什么我必须写elms[i].style['animationDelay]而不是animation-delay才能使其工作吗?为什么Chrome会在cur+dur秒后播放动画,而Firefox会直接在cur秒后播放动画而没有延迟呢? - tryzor
@tryzor 我明白你的意思。我一直在看它,它让我感到很疯狂。谢谢你指出来... - tiffon

0

老版 Firefox (至少到16),Opera 在迁移到 Blink 之前(<15),IE 至少是10 - 如果我们只更改动画的某些属性,如 (-prefix-)animation-delay,它们将不会重新绘制动画。为了使它们这样做,我们必须应用一些更深入的技巧。

  1. 首先是删除并重新插入动画元素。而且 - 为了 Webkit 的安全 - 在其上应用所有样式更改。

只需更改 @tiffon 的 fiddle 代码即可。

elms[i].style.setProperty(prop, (cur + delay) + 's');

var newEl =  elms[i].cloneNode(true);
newEl.style.setProperty(prop, (cur + delay) + 's', '');
elms[i].parentNode.replaceChild(newEl,elms[i]);

http://jsfiddle.net/FHuKN/28/

  1. 移除动画所附加的类名或属性值,等待一段时间(setTimeout),或者更好的方法是触发回流(例如,element.offsetWidth = element.offsetWidth;),然后再次添加类名。

http://jsfiddle.net/FHuKN/29/

这个想法不是我自己的,所有的功劳归于Chris Coyer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接