1

如何检测由css3动画或网页动画(Element.animate)所做的更改?如何检测由CSS3动画或Web动画API所做的更改?

(对不起,我的英文不好!这是我在#1的第一个问题)

我知道MutationObserver,它只是如果我改变内嵌样式或者如果我使用requestAnimationFrame(因为我用它更改内联样式)响应。但是如果我使用css3动画或Web动画,MutationObserver不会响应,因为它们不会更改内联样式。

看到这里...这里有两个div ... div1,div2。当div2的位置改变时,div1的位置将会改变。但是这只有在我使用requestAnimationFrame的时候才会发生。

我的问题是我怎样才能做到这一点的css3动画和网页动画(Element.animate)?

var div1 = document.getElementById("div1"); 
 
var div2 = document.getElementById("div2"); 
 

 
/***** Add mutation observer to detect change *****/ 
 

 
var mutation = new MutationObserver(function(mutations) { 
 
    div1.style.left = div2.style.left; 
 
}); 
 
mutation.observe(div2, { 
 
    attributes: true 
 
}); 
 

 
/***** Animation with css *****/ 
 

 
function cssAnimation() { 
 
    div2.style.animation = "anim 1.5s linear"; 
 
} 
 

 
/***** Animation with web animations *****/ 
 

 
function webAnimation() { 
 
    div2.animate({ 
 
    left: [0, "500px"] 
 
    }, { 
 
    duration: 1500, 
 
    easing: "linear" 
 
    }); 
 
} 
 

 
/*****Animation with requestAnimationFrame ******/ 
 

 
//Current left position of div2 
 
var left = 0; 
 

 
function requestAnimation() { 
 
    //Increase left position 5px per keyframe 
 
    div2.style.left = `${(left += 5)}px`; 
 

 
    //Increase left position until it reaches to 500px 
 
    if (left < 500) { 
 
    requestAnimationFrame(requestAnimation); 
 
    } 
 
} 
 

 
function clearAnimations() { 
 
    left = 0; 
 
    div2.style.left = 0; 
 
    div2.style.animation = "unset"; 
 
}
@keyframes anim { 
 
    from { 
 
    left: 0; 
 
    } 
 
    to { 
 
    left: 500px; 
 
    } 
 
} 
 

 
#div1 { 
 
    background: orange; 
 
    width: 100px; 
 
    height: 100px; 
 
    position: absolute; 
 
    top: 200px; 
 
} 
 

 
#div2 { 
 
    background: lightgreen; 
 
    width: 100px; 
 
    height: 100px; 
 
    position: absolute; 
 
    top: 100px; 
 
}
<div id="buttons"> 
 
    <h3>Animate with...</h3> 
 
    <button onclick='cssAnimation()'>Css3</button> 
 
    <button onclick="requestAnimation()">request animation frame</button> 
 
    <button onclick="webAnimation()">web animations api</button> 
 
    <button id="clear" onclick="clearAnimations()">Clear</button> 
 
</div> 
 

 
<div id="div1"> 
 
    Div1 
 
</div> 
 
<div id="div2"> 
 
    div2 
 
</div>

+0

什么时候你想检测到CSS的变化? – guest271314

+0

我知道我可以使用animationstart并通过setInterval进行更新,直到animationend事件发生时发生clearInterval。但它有性能问题。 –

+0

@IbrahimAlKhalil你为什么要用setInterval?绝对没有必要。请阅读css动画和课程。你正在接近这完全错误的。 – Darkrum

回答

0

对CSS动画,你有animationstart和animationend事件,可以帮助您与您试图实现的目标。然而,没有动画变化动画更新事件,就我所知,这是通过设计。在动画发生期间没有事件的情况下,可以达到完全的硬件加速,插值计算直接在GPU中完成。所以,请注意,虽然您可能能够通过animationstart,animationend和requestAnimationFrame模仿animationchange事件会做什么,但这可能会涉及性能损失。

+0

谢谢!我只在这里使用了左边的属性。其实我在我的项目中使用了translate3d。 –

0

你已经过了复杂的事情。但要听取动画的变化,你可以听取这些事件,而不是突变观察者。

animationstart //will fire has soon as the animation starts 
animationiteration //will fire if the same animation is looped can be infinity or more then 2 
animationend // will fire when the animations have ended 

也请使用translate来代替动画左边的属性。

+0

谢谢!我只在这里使用了左边的属性。其实我在我的项目中使用了translate3d。 –

-1

您可以使用​​和window.getComputedStyle()动画,注意过程中获取当前的动画风格,在Element.animate()呼叫

var div1 = document.getElementById("div1"); 
 
var div2 = document.getElementById("div2"); 
 

 
/***** Add mutation observer to detect change *****/ 
 

 
var mutation = new MutationObserver(function(mutations) { 
 
    div1.style.left = div2.style.left; 
 
}); 
 
mutation.observe(div2, { 
 
    attributes: true 
 
}); 
 

 
/***** Animation with css *****/ 
 

 
function cssAnimation() { 
 
    div2.style.animation = "anim 1.5s linear forwards"; 
 
    let animationFrame; 
 

 
    function getCurrentStyles() { 
 
    console.log(window.getComputedStyle(div2).left); 
 
    animationFrame = requestAnimationFrame(getCurrentStyles) 
 
    } 
 
    getCurrentStyles(); 
 
    div2.addEventListener("animationend",() => cancelAnimationFrame(animationFrame)); 
 
} 
 

 
/***** Animation with web animations *****/ 
 

 
function webAnimation() { 
 
    let animationFrame; 
 

 
    function getCurrentStyles() { 
 
    console.log(window.getComputedStyle(div2).left); 
 
    animationFrame = requestAnimationFrame(getCurrentStyles) 
 
    } 
 
    getCurrentStyles(); 
 
    div2.animate({ 
 
    left: [0, "500px"] 
 
    }, { 
 
    duration: 1500, 
 
    fill: "forwards", 
 
    easing: "linear" 
 
    }).onfinish = function() { 
 
    cancelAnimationFrame(animationFrame); 
 
    console.log(window.getComputedStyle(div2).left); 
 
    }; 
 
} 
 

 
/*****Animation with requestAnimationFrame ******/ 
 

 
//Current left position of div2 
 
var left = 0; 
 

 
function requestAnimation() { 
 
    //Increase left position 5px per keyframe 
 
    div2.style.left = `${(left += 5)}px`; 
 
    console.log(window.getComputedStyle(div2).left); 
 
    //Increase left position until it reaches to 500px 
 
    if (left < 500) { 
 
    requestAnimationFrame(requestAnimation); 
 
    } 
 
} 
 

 
function clearAnimations() { 
 
    left = 0; 
 
    div2.style.left = 0; 
 
    div2.style.animation = "unset"; 
 
}
@keyframes anim { 
 
    from { 
 
    left: 0; 
 
    } 
 
    to { 
 
    left: 500px; 
 
    } 
 
} 
 

 
#div1 { 
 
    background: orange; 
 
    width: 100px; 
 
    height: 100px; 
 
    position: absolute; 
 
    top: 200px; 
 
} 
 

 
#div2 { 
 
    background: lightgreen; 
 
    width: 100px; 
 
    height: 100px; 
 
    position: absolute; 
 
    top: 100px; 
 
}
<div id="buttons"> 
 
    <h3>Animate with...</h3> 
 
    <button onclick='cssAnimation()'>Css3</button> 
 
    <button onclick="requestAnimation()">request animation frame</button> 
 
    <button onclick="webAnimation()">web animations api</button> 
 
    <button id="clear" onclick="clearAnimations()">Clear</button> 
 
</div> 
 

 
<div id="div1"> 
 
    Div1 
 
</div> 
 
<div id="div2"> 
 
    div2 
 
</div>

+0

感谢bro,你必须使用每个动画方法手动使用onfinish,你怎么知道元素将使用动画方法进行动画制作。 –

+0

_“你怎么知道一个元素将使用动画方法进行动画制作。”_因为这就是你的代码在那个代码块中所做的。包含使用'requestAnimationFrame()'的CSS动画和动画的相同方法。你是否试图提出一个假设的问题,其中动画实现的类型未知?或者你是否真的试图找到一个解决方案给定的问题代码? – guest271314

+0

请参阅https://atomiks.github.io/tippyjs/如果通过为工具提示设置动画来更改目标元素的翻译或左/右属性,则会出现粘滞的工具提示,并且会跟随目标并重新定位。 –

0

两个CSS动画和Web动画包括fill:"forward"是基于原则您将动画的播放委托给浏览器。这允许浏览器在可能的情况下在单独的线程或进程上运行动画,以便它可以顺利运行。尽可能避免在每个框架上更新来自JavaScript的样式。

在你的例子中,你能简单地在两个元素上同时运行动画吗?至少,Web动画允许同步动画。

当网页动画API的其余部分出厂时,从一个元素复制动画并将其应用到另一个元素会容易得多,但现在您需要拨打animate两次。

正如其他人所指出的那样,可以观察动画回放中的重要时刻(当它们开始,结束,重复等),但是没有事件在每个帧上运行。如果您想要在每个框架上执行和操作,则需要使用​​。

如果您在​​传递div2getComputedStyle你会得到该帧,然后可以申请div1动画风格。 (也就是说,div2.style.left只会给你通过style属性指定的样式,但getComputedStyle(div2).left会给你动画样式,包括CSS动画和Web动画的样式变化)。但是,这又会导致性能下降,并且两个动画不一定会同步,因为CSS动画或Web动画可能运行在不同的线程或进程上。