如何检测css3动画或网络动画(Element.animate)所做的更改?
(抱歉我的英文不好!这是我在Stackoverflow中的第一个问题)
我知道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";
}
&#13;
@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;
}
&#13;
<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>
&#13;
答案 0 :(得分:0)
对于css动画,你有animationstart和animationend事件可以帮助你实现你想要实现的目标。但是,没有 animationchange 或 animationupdate 事件,据我所知,这是设计方式。在动画发生期间没有事件,可以实现全硬件加速,直接在GPU中完成插值计算。所以,请注意,虽然您可以通过animationstart,animationend和requestAnimationFrame来模仿animationchange事件的作用,但这可能会导致性能下降。
答案 1 :(得分: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
也请使用翻译而不是动画左侧属性。
答案 2 :(得分:0)
CSS动画和Web动画都基于您将动画播放委派给浏览器的原则。这允许浏览器在可能的情况下在单独的线程或进程上运行动画,以便它顺利运行。在可能的情况下,最好避免在每个帧上从JavaScript更新样式。
在您的示例中,您是否可以同时在两个元素上运行动画?至少,Web动画允许同步动画。
当发布Web动画API的其余部分时,从一个元素复制动画并将其应用到另一个元素会更容易,但现在需要两次调用animate
。
正如其他人所指出的那样,可以观察到动画播放中的重要时刻(当它们开始,结束,重复等)时,但是没有在每个帧上运行的事件。如果您想对每个帧执行操作,则需要使用requestAnimationFrame
。
如果您将div2
传递给getComputedStyle
中的requestAnimationFrame
,您将获得该框架的动画样式,然后您可以将其应用于div1
。 (也就是说,阅读div2.style.left
只会为您提供通过style
属性指定的样式,但getComputedStyle(div2).left
将为您提供动画样式,包括CSS动画和Web动画的样式更改)。但是,再次,这将导致性能不佳,并且两个动画不一定会同步,因为CSS动画或Web动画可能在不同的线程或进程上运行。
答案 3 :(得分:-1)
您可以使用requestAnimationFrame
和window.getComputedStyle()
来获取动画期间的当前动画样式,注意fill:"forward"
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";
}
&#13;
@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;
}
&#13;
<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>
&#13;