如何让javascript控制css3的animation和transition,让css3反复执行?

我们现在想通过按钮的click事件反复触发一个元素的css3动画,点击一次,动画效果就跑一次。现在碰到这样一个问题,我通过click事件给目标元素添加一个带有css3动画的class,动画效果第一次有,后续就不再触发css3动画了。click事件中先删除class再添加还是不行,怎么办?(后面附有测试代码线上链接)
clipboard.png
测试代码线上链接如下:
线上测试代码

阅读 19.4k
8 个回答

刚过来就看到看到正确答案真是悲伤的故事。
那我就来稍微解释一下为何setTimeout 0在这里能够起到效果吧。
如果没有setTimeout 0,浏览器的执行流程是这样的:
removeClass,然后addClass,然后让浏览器重新渲染完整个元素属性。这样就不会有transition动画效果了。
其实setTimeout 0的作用相当于把内部代码放到当前上下文的最后去执行,在这个问题中的作用就相当于是
removeClass,然后让浏览器重新渲染完整个元素属性,然后addClass
如果解释的不对还请dalao谅解并指出问题。

let [testDiv01,testDiv02,testBtn01,testBtn02]=[$('#testDiv01'),$('#testDiv02'),$('#testBtn01'),$('#testBtn02')];

testBtn01.on('click',function () {

testDiv01.removeClass('transi');

    setTimeout(function(){
     testDiv01.addClass('transi');
  },0)

});

testBtn02.on('click',function () {

testDiv02.removeClass('ani');
    setTimeout(function(){
        testDiv02.addClass('ani');
    },0)

});

这是浏览器渲染机制导致的。

页面等待js线程执行完毕,随后执行GUI线程渲染,而removeClass随后addClass这样的代码,对于GUI线程来说页面上没有任何改变,自然不会做任何动作。

而设置了setTimeout之后,执行顺序为 js线程执行完毕 -> GUI线程渲染(此时页面的class已去除)-> 异步线程执行完毕 -> GUI线程渲染(此时页面的class已添加)

在这样的机制下,如果你把removeClassaddClass同时放在setTimeout中,设置时间间隔大于一定时间(w3c标准是25ms,但实际能分辨的最小时间间隔会更小一点,因浏览器而异),也有同样的效果。

哈哈哈哈哈哈哈
楼上都不够优雅

testBtn01.on('click',function () {
    testDiv01.removeClass('transi');
    testDiv01.width(); // Apply change
    testDiv01.addClass('transi');
});

浏览器优化,会先计算最终样式最后再同步。计算其宽高等当前样式能强制同步样式再继续执行。

你可以点击按钮加类名,然后监听动画完成,动画完成时删除类名

如果你是想让你的类名点一下删除然后再添加的话,改成这样就好了,不知是不是你想要的效果
testDiv01.toggleClass('transi');

你的代码里点击事件触发立马添加移除class是不行的,起码要做延时再移除,可以试试这样

testBtn01.on('click',function () {
        
        testDiv01.addClass('transi');
        let t = setTimeout(()=>{
            testDiv01.removeClass('transi');
            clearTimeout(t);
        },500);

});

可以选择给它加个setTimeout()函数,让它过几毫秒,删除这个类,
`testBtn01.on('click',function(){

 testDiv01.addClass('transi');
 setTimeout(function(){
    testDiv01.removeClass('transi');
 },500);

});`

推荐问题
宣传栏