javascript - 在 CSS3 中重新啟動動畫:有比移除元素更好的方法嗎?
我有一個需要在點擊時重新啟動的 CSS3 動畫。它是一個顯示剩餘時間的條。我正在使用 scaleY(0) 轉換來製作這個效果。
現在我需要通過將條形恢復到 scaleY(1) 來重新啟動動畫,然後再讓它變回 scaleY(0)。我第一次嘗試設置 scaleY(1) 失敗了,因為它需要相同的 15 秒才能恢復到全長。即使我將持續時間改為 0.1 秒,我也需要延遲或鏈接 scaleY(0) 的賦值,以讓條形補充完成。對於這麼簡單的任務,這感覺太複雜了。
我還發現了一個有趣的小技巧,可以通過將元素從文檔中移除,然後重新插入它的克隆來重新啟動動畫:http://css-tricks.com/restart-css-animation/
它有效,但有沒有更好的方式來重新啟動 CSS 動畫?我正在使用 Prototype 和 Move.js,但我並不限於使用它們。
答案#1
不需要使用 timeout,使用 reflow 來應用更改:
function reset_animation() {
var el = document.getElementById('animated');
el.style.animation = 'none';
el.offsetHeight; /* trigger reflow */
el.style.animation = null;
}#animated {
position: absolute;
top: 70px;
width: 50px; height: 50px;
background-color: black;
animation: bounce 3s ease-in-out infinite;
}
@keyframes bounce {
0% { left: 0; }
50% { left: calc( 100% - 50px ); }
100% { left: 0; }
}<div id="animated"></div>
<button onclick="reset_animation()">Reset</button>答案#2
只需透過 JavaScript 設定 animation 屬性為 "none",然後設定一個 timeout 將該屬性改回 "",這樣它就會再次繼承自 CSS。
這裡是 Webkit 的示範:http://jsfiddle.net/leaverou/xK6sa/ 但是,請記住,在現實使用中,你也應該至少包含 -moz-。
答案#3
@ZachB 關於 Web Animation API 的回答看起來像是做這件事的「正確」™方式,但不幸的是似乎需要你透過 JavaScript 來定義你的動畫。不過它吸引了我的注意,我找到了一些相關的、有用的東西:
Element.getAnimations() 和 Document.getAnimations()
到 2021 年為止,他們的支援相當不錯。
就我而言,我想同時重新啟動頁面上的所有動畫,所以我只需要這樣做:
const replayAnimations = () => {
document.getAnimations().forEach((anim) => {
anim.cancel();
anim.play();
});
};
但在大多數情況下,人們可能會想選擇他們要重新啟動的動畫…
getAnimations 會回傳一堆看起來像這樣的 CSSAnimation 和 CSSTransition 物件:
animationName: "fade"
currentTime: 1500
effect: KeyframeEffect
composite: "replace"
pseudoElement: null
target: path.line.yellow
finished: Promise {<fulfilled>: CSSAnimation}
playState: "finished"
ready: Promise {<fulfilled>: CSSAnimation}
replaceState: "active"
timeline: DocumentTimeline {currentTime: 135640.502}
...etc
因此,你可以使用 animationName 和 target 屬性來選擇你想要的動畫(儘管方式有點繞)。
編輯
這裡有一個方便的函數,它可能更適合只使用 Document.getAnimations,並加入 TypeScript 作為示範:
// restart animations on a given dom element
export const restartAnimations = (element: Element): void => {
for (const animation of document.getAnimations()) {
if (
animation.effect instanceof KeyframeEffect &&
element.contains(animation.effect.target)
) {
animation.cancel();
animation.play();
}
}
};
答案#4
- 將動畫實作為 CSS 描述符
- 將描述符添加到元素以開始動畫
- 使用
animationend事件處理函數在動畫完成時移除描述符,以便下次想重新啟動動畫時可以再次添加。
HTML
<div id="animatedText">
Animation happens here
</div>
<script>
function startanimation(element) {
element.classList.add("animateDescriptor");
element.addEventListener( "animationend", function() {
element.classList.remove("animateDescriptor");
} );
}
</script>
<button onclick="startanimation(
document.getElementById('animatedText') )">
Click to animate above text
</button>
CSS
@keyframes fadeinout {
from { color: #000000; }
25% {color: #0000FF; }
50% {color: #00FF00; }
75% {color: #FF0000; }
to { color : #000000; }
}
.animateDescriptor {
animation: fadeinout 1.0s;
}
在這裡試試看:jsfiddle
