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動畫可能運行在不同的線程或進程上。