如何检测由CSS3动画或Web动画API所做的更改?
如何检测由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>
对CSS动画,你有animationstart和animationend事件,可以帮助您与您试图实现的目标。然而,没有动画变化或动画更新事件,就我所知,这是通过设计。在动画发生期间没有事件的情况下,可以达到完全的硬件加速,插值计算直接在GPU中完成。所以,请注意,虽然您可能能够通过animationstart,animationend和requestAnimationFrame模仿animationchange事件会做什么,但这可能会涉及性能损失。
谢谢!我只在这里使用了左边的属性。其实我在我的项目中使用了translate3d。 –
你已经过了复杂的事情。但要听取动画的变化,你可以听取这些事件,而不是突变观察者。
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来代替动画左边的属性。
谢谢!我只在这里使用了左边的属性。其实我在我的项目中使用了translate3d。 –
您可以使用和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>
感谢bro,你必须使用每个动画方法手动使用onfinish,你怎么知道元素将使用动画方法进行动画制作。 –
_“你怎么知道一个元素将使用动画方法进行动画制作。”_因为这就是你的代码在那个代码块中所做的。包含使用'requestAnimationFrame()'的CSS动画和动画的相同方法。你是否试图提出一个假设的问题,其中动画实现的类型未知?或者你是否真的试图找到一个解决方案给定的问题代码? – guest271314
请参阅https://atomiks.github.io/tippyjs/如果通过为工具提示设置动画来更改目标元素的翻译或左/右属性,则会出现粘滞的工具提示,并且会跟随目标并重新定位。 –
两个CSS动画和Web动画包括fill:"forward"
是基于原则您将动画的播放委托给浏览器。这允许浏览器在可能的情况下在单独的线程或进程上运行动画,以便它可以顺利运行。尽可能避免在每个框架上更新来自JavaScript的样式。
在你的例子中,你能简单地在两个元素上同时运行动画吗?至少,Web动画允许同步动画。
当网页动画API的其余部分出厂时,从一个元素复制动画并将其应用到另一个元素会容易得多,但现在您需要拨打animate
两次。
正如其他人所指出的那样,可以观察动画回放中的重要时刻(当它们开始,结束,重复等),但是没有事件在每个帧上运行。如果您想要在每个框架上执行和操作,则需要使用。
如果您在传递div2
到getComputedStyle
你会得到该帧,然后可以申请div1
动画风格。 (也就是说,div2.style.left
只会给你通过style
属性指定的样式,但getComputedStyle(div2).left
会给你动画样式,包括CSS动画和Web动画的样式变化)。但是,这又会导致性能下降,并且两个动画不一定会同步,因为CSS动画或Web动画可能运行在不同的线程或进程上。
什么时候你想检测到CSS的变化? – guest271314
我知道我可以使用animationstart并通过setInterval进行更新,直到animationend事件发生时发生clearInterval。但它有性能问题。 –
@IbrahimAlKhalil你为什么要用setInterval?绝对没有必要。请阅读css动画和课程。你正在接近这完全错误的。 – Darkrum