ä½¿ç¨ Web å¨ç» API
web å¨ç» API å¯ä»¥è®©æä»¬ç¨ JavaScript åå¨ç»å¹¶ä¸æ§å¶å¨ç»ãæ¬æå°éè¿æè¶£ç demo åæå¦ï¼ä»¥æè¶£çæ¹å¼å¼å¯ä½ 对è¿çç±ä¸½ä¸ä»å¢çæ¢ç´¢ã
è®¤è¯ Web å¨ç» API
Web å¨ç» APIå°æµè§å¨å¨ç»å¼æåå¼åè
æå¼ï¼å¹¶ç± JavaScript è¿è¡æä½ãè¿äº API 被设计æ CSS Animations and CSS Transitionsçæ¥å£ï¼æªæ¥ä¼å¯¹è¿äº API åè¡¥å
以䏰坿´å¤çåè½ã宿¯å¯¹ç½ç»ä¸å¨ç»åçæ¯ææææçæ¹å¼ä¹ä¸ï¼è®©æµè§å¨è¿è¡èªå·±çå
é¨ï¼ä¸éè¦ hacksï¼æè
å¼ºè¿«ï¼æè
Window.requestAnimationFrame()ã
éè¿ Web å¨ç» APIï¼æä»¬å¯ä»¥å°äº¤äºå¼å¨ç»ä»æ ·å¼è¡¨ç§»å¨å° JavaScriptï¼å°è¡¨ç°ä¸è¡ä¸ºåå¼ãæä»¬ä¸åéè¦ä¾èµ DOM éçææ¯ï¼å¦å° CSS 屿§åèå´ç±»åå ¥å ç´ æ¥æ§å¶ææ¾æ¹åãä¸çº¯ç²¹ç声æå¼ CSS ä¸åï¼JavaScript è¿å 许æä»¬å¨æå°å°å±æ§å¼è®¾ç½®ä¸ºæç»æ¶é´ãå¯¹äºæå»ºèªå®ä¹å¨ç»åºåå建交äºå¼å¨ç»ï¼Web å¨ç» API å¯è½æ¯å®æå·¥ä½çå®ç¾å·¥å ·ã让æä»¬ççå®è½åä»ä¹ï¼
æµè§å¨å ¼å®¹æ åµ
é»è®¤æ åµä¸ï¼Firefox 48+ å Chrome 36+ 䏿ä¾äºæ¬æä¸è®¨è®ºçåºæ¬ Web å¨ç» API åè½ãWebkit å Edge å·²ç»å° API ç§»å¨å°åèªçå¾ åäºé¡¹å表ä¸ï¼ä½æ¯ç´å°æä»¬çå°æææµè§å¨é½æå®æ´çæ¯æï¼æä»¥æä¸ä¸ªä¾¿äºç»´æ¤ç polyfillï¼ handy maintained polyfillï¼å¯ä»¥æµè¯åè½æ¯æï¼å¹¶å¨å¿ è¦æ¶æ·»å å®ã
ç¨ Web å¨ç» API å CSS å¨ç»
å¦ä¹ Web å¨ç» API çæ´ä¸ºçæçæ¹æ³ä¹ä¸æ¯ä»å¤§å¤æ°ç½ç»å¼å人åå¼å§ä½¿ç¨ä»¥åç CSS å¨ç»ãCSS å¨ç»æä¸ä¸ªçæçè¯æ³ï¼å¾å¥½å°å解为æ¼ç¤ºç®çã
CSS çæ¬
è¿æ¯ä¸ä¸ªç¨ CSS åçæ»å¨å¨ç»ï¼æ¾ç¤ºç±ä¸½ä¸è½ä¸éåä»å¢çå åæ´ï¼åè§ Codepen ä¸ç宿´ä»£ç ï¼ï¼
请注æèæ¯çç§»å¨ï¼ç±ä¸½ä¸çæè½¬ï¼ä»¥å她çé¢è²åç§»ååãæ¬æç¨æä»¬å°ä» ä» å ³æ³¨ç±ä¸½ä¸ãè¿æ¯æ§å¶ç±ä¸½ä¸å¨ç»çç®åç CSSï¼
#alice {
animation: aliceTumbling infinite 3s linear;
}
@keyframes aliceTumbling {
0% {
color: #000;
transform: rotate(0) translate3D(-50%, -50%, 0);
}
30% {
color: #431236;
}
100% {
color: #000;
transform: rotate(360deg) translate3D(-50%, -50%, 0);
}
}
è¿æ ·å¯ä»¥ä»¥æå®çï¼çº¿æ§ï¼éçå¨ 3 ç§å
æ¹åç±ä¸½ä¸çé¢è²å忢çæè½¬ï¼å¹¶æ é循ç¯ãå¨ @keyframes åä¸ï¼æä»¬å¯ä»¥çå°æ¯ä¸ªå¾ªç¯ï¼çº¦ 0.9 ç§ï¼ç 30ï¼
ï¼Alice çé¢è²ä»é»è²å为深红è²ï¼ç¶åå¨å¾ªç¯ç»ææ¶å次è¿åã
å°å ¶ç§»å¨å° JavaScript
ç°å¨è®©æä»¬å°è¯ä½¿ç¨ Web å¨ç» API å建ç¸åçå¨ç»ã
è¡¨ç¤ºå ³é®å¸§
æä»¬é¦å
è¦åçæ¯å建ä¸ä¸ªå¯¹åºäºæä»¬ç CSS @keyframes åçå
³é®å¸§å¯¹è±¡ï¼
const aliceTumbling = [
{ transform: "rotate(0) translate3D(-50%, -50%, 0)", color: "#000" },
{ color: "#431236", offset: 0.3 },
{ transform: "rotate(360deg) translate3D(-50%, -50%, 0)", color: "#000" },
];
è¿éæä»¬ä½¿ç¨ä¸ä¸ªå å«å¤ä¸ªå¯¹è±¡çæ°ç»ãæ¯ä¸ªå¯¹è±¡ä»£è¡¨åå§ CSS ä¸çä¸ä¸ªé®ãç¶èï¼ä¸ CSS ä¸åï¼Web å¨ç» API ä¸éè¦æç¡®å°åç¥æ¯ä¸ªé®åºç°çå¨ç»çç¾åæ¯ãå®å°æ ¹æ®ä½ ç»åºçæé®æ°éèªå¨å°å¨ç»åå为ç¸ççé¨åãè¿æå³çå ·æä¸ä¸ªé®çå ³é®å¸§å¯¹è±¡å°éè¿å¨ç»çæ¯ä¸ªå¾ªç¯çæ¹å¼ææ¾ä¸é´é®ï¼é¤éå¦æè¯´æã
彿们æ³è¦æç¡®å°è®¾ç½®ä¸ä¸ªé®ä¸å ¶ä»é®çåç§»éæ¶ï¼æä»¬å¯ä»¥ç´æ¥å¨å¯¹è±¡ä¸æå®ä¸ä¸ªåç§»éï¼å¹¶ä¸éå·åéãå¨ä¸é¢çä¾åä¸ï¼ä¸ºäºç¡®ä¿ç±ä¸½ä¸çé¢è²åå为 30ï¼ è䏿¯ 50ï¼ ï¼æä»¬ç»å®çåç§»é为 0.3ã
å¿
é¡»è³å°æå®ä¸¤ä¸ªå
³é®å¸§ï¼è¡¨ç¤ºå¨ç»åºåçå¼å§åç»æç¶æï¼.å¦æä½ çå
³é®å¸§åè¡¨åªæä¸ä¸ªæ¡ç®ï¼Element.animate() å°æåºä¸æ¯æçå¼å¸¸æ¥éã
æä»¥è¦å顾ä¸ä¸ï¼é¤éä½ æå®ä¸ä¸ªé®ä¸çåç§»éï¼å¦åé®çé»è®¤å¼æ¯çé´éçãæ¹ä¾¿åï¼
表示æ¶é´å±æ§
æä»¬è¿éè¦å建ä¸ä¸ªå®æ¶å±æ§ç对象对åºäºç±ä¸½ä¸å¨ç»ä¸çå¼ï¼
const aliceTiming = {
duration: 3000,
iterations: Infinity,
};
ä½ ä¼æ³¨æå°è¿éæä¸äºå·®å¼ï¼å¦ä½å¨ CSS ä¸è¡¨ç¤ºçä»·çå¼ï¼
- 第ä¸ä¸ªæ¯ï¼æç»æ¶é´æ¯æ¯«ç§ï¼è䏿¯ç§ââ3000 䏿¯ 3 ç§ãå
setTimeout()åWindow.requestAnimationFrame()ï¼Web å¨ç» API åªæ¯ææ¯«ç§ã - ä½ ä¼æ³¨æå°çå¦ä¸ä»¶äºæ¯ï¼å®æ¯
iterationsï¼è䏿¯iteration-countã
夿³¨ï¼CSS å¨ç»ä¸ä½¿ç¨ç屿§å¼ä¸ Web å¨ç»ä¸ä½¿ç¨ç屿§å¼åå¨ä¸äºå°çå·®å¼ãæ¯å¦ï¼Web å¨ç»ä¸ä¸è½ä½¿ç¨å符串âinfiniteâï¼èæ¯ä½¿ç¨ Javascript çå
³é®å Infinityã以åæä»¬ç¨ easing æ¥ä»£æ¿timing-functionãæä»¬ä¸å¿
å¨è¿ååºeasingçå¼ï¼å 为ä¸åå¨ CSS å¨ç»éï¼é»è®¤ç"animation-timing-function"æ¯easeã页é¢å¨ç» API çé»è®¤ easing æ¯linearâ èè¿å°±æ¯æä»¬æ³è¦çã
æ´åè¿äºç¹æ§
æ¯æ¶åæè¿äºç¹æ§ç»åå°ä¸èµ·è¿ç¨äº Element.animate() :
document.getElementById("alice").animate(aliceTumbling, aliceTiming);
And boom: the animation starts playing (see the finished version on Codepen).
å¯ä»¥å¨å¯ä»¥ä½¿ç¨ CSS å¨ç»åçä»»ä½ DOM å ç´ ä¸è°ç¨ animate() æ¹æ³ãå®å¯ä»¥ç¨å ç§æ¹å¼åæãæä»¬å¯ä»¥ç´æ¥åè¿æ ·ä¼ éä»ä»¬çå¼ï¼èä¸éè¦ä¸ºå ³é®å¸§åæ¶é´å±æ§å建对象ï¼
document.getElementById("alice").animate(
[
{ transform: "rotate(0) translate3D(-50%, -50%, 0)", color: "#000" },
{ color: "#431236", offset: 0.3 },
{ transform: "rotate(360deg) translate3D(-50%, -50%, 0)", color: "#000" },
],
{
duration: 3000,
iterations: Infinity,
},
);
æ´éè¦çæ¯ï¼å¦ææä»¬åªæ³æå®å¨ç»çæç»æ¶é´ï¼è䏿¯å ¶è¿ä»£ï¼é»è®¤å¨ç»è¿ä»£ä¸æ¬¡ï¼ï¼æä»¬å¯ä»¥åç¬ä¼ 鿝«ç§ï¼
document.getElementById("alice").animate(
[
{ transform: "rotate(0) translate3D(-50%, -50%, 0)", color: "#000" },
{ color: "#431236", offset: 0.3 },
{ transform: "rotate(360deg) translate3D(-50%, -50%, 0)", color: "#000" },
],
3000,
);
ä½¿ç¨ play()ãpause()ãreverse() å updatePlaybackRate() æ§å¶ææ¾
è½ç¶æä»¬å¯ä»¥ä½¿ç¨ Web å¨ç» API ç¼å CSS å¨ç»ï¼å ¶ä¸ API çæ£æ´¾ä¸ç¨åºçæ¯æçºµå¨ç»çææ¾ãWeb å¨ç» API æä¾äºä¸äºæ§å¶ææ¾çæç¨æ¹æ³ã让æä»¬æ¥ççå¨ Growing / Shrinking Alice 游æä¸æååææ¾å¨ç»ï¼è¯·æ¥ç Codepen ä¸ç宿´ä»£ç ï¼ï¼
å¨è¿ä¸ªæ¸¸æä¸ï¼ç±ä¸½ä¸æä¸ä¸ªå¨ç»ï¼ä½¿å¥¹ä»å°å°å¤§ï¼æä»¬éè¿ä¸ä¸ªç¶ååä¸ä¸ªèç³æ§å¶ãè¿ä¸¤ä¸ªé½æèªå·±çå¨ç»ã
æååå¯å¨å¨ç»
ç¨åæä»¬ä¼å讨论ç±ä¸½ä¸çå¨ç»ï¼ä½ç°å¨æä»¬æ¥ççèç³çå¨ç»ï¼
const nommingCake = document
.getElementById("eat-me_sprite")
.animate(
[{ transform: "translateY(0)" }, { transform: "translateY(-80%)" }],
{
fill: "forwards",
easing: "steps(4, end)",
duration: aliceChange.effect.getComputedTiming().duration / 2,
},
);
Element.animate() æ¹æ³ä¼å¨è°ç¨åç«å³æ§è¡ã为äºé²æ¢èç³å¨ç¨æ·ææºä¼ç¹å»ä¹åè¿é£èªå·±ï¼æä»¬è°ç¨ Animation.pause() ï¼å¦ä¸ï¼
nommingCake.pause();
æä»¬å¯ä»¥è¿è¡ Animation.play() æ¹æ³ï¼
nommingCake.play();
ç¹å«å°ï¼æä»¬æ³å°å ¶é¾æ¥å°ç±ä¸½ä¸çå¨ç»ï¼æä»¥å½èç³è¢«åææ¶ï¼å¥¹å徿´å¤§ãæä»¬å¯ä»¥éè¿ä»¥ä¸åè½æ¥å®ç°ï¼
const growAlice = () => {
// ææ¾ç±ä¸½ä¸çå¨ç»ã
aliceChange.play();
// ææ¾èç³çå¨ç»ã
nommingCake.play();
};
å½ç¨æ·æ¡ä½é¼ æ æè
å¨è§¦æ¸å±ä¸æä½ä»ä»¬çææå¨èç³ä¸æ¶ï¼æä»¬ç°å¨å¯ä»¥è°ç¨ growAlice æ¥ä½¿ææå¨ç»åæ¥ä½ç¨ï¼
cake.addEventListener("mousedown", growAlice, false);
cake.addEventListener("touchstart", growAlice, false);
å ¶ä»æç¨çæ¹æ³
é¤äºæååææ¾ï¼æä»¬å¯ä»¥ä½¿ç¨ä»¥ä¸å¨ç»æ¹æ³ï¼
Animation.finish()å¨ç»ç»æãAnimation.cancel()ç»æ¢å¨ç»ãAnimation.reverse()ååææ¾å¨ç»ãç¸å½äºè®¾ç½®å¨ç»ææ¾é度ï¼Animation.playbackRateï¼ä¸ºè´å¼ï¼å¹¶ææ¾ã
让æä»¬å æ¥çä¸ä¸ playbackRateââä¸ä¸ªè´å¼çææ¾é度å°å¯¼è´ä¸ä¸ªå¨ç»ååææ¾ãå½ç±ä¸½ä¸ä»ç¶ä¸åé æ¶ï¼å¥¹è¶æ¥è¶å°ãè¿æ¯å 为ç¶åå°å¨ç»çææ¾éåº¦ä» 1 æ´æ¹ä¸º -1ï¼
const shrinkAlice = () => {
aliceChange.playbackRate = -1;
aliceChange.play();
};
bottle.addEventListener("mousedown", shrinkAlice, false);
bottle.addEventListener("touchstart", shrinkAlice, false);
å¨ç±ä¸½ä¸éä¸å¥éè®°ä¸ï¼ç±ä¸½ä¸æ è¡å°ä¸ä¸ªä¸çï¼å¥¹å¿ é¡»å¨åºæ¯ä¸è·æ¥ââèä¸ä»¥ä¸¤åçé度快éåè¿ï¼å¨çº¢å¥³çæ¯èµçä¾åä¸ï¼ç±ä¸½ä¸åçº¢å¥³çæ£å¨åºæ¯ä¸è·æ¥ï¼æ¥ç Codepen ä¸ç宿´ä»£ç ï¼ï¼
å 为å°å©åå¾å®¹æç²æ«ä¸å ªï¼ä¸åèªå¨æºæ£åï¼ç±ä¸½ä¸ä¸æåéãæä»¬å·²ç»éè¿å¨å¨ç»ææ¾æ¶è®¾ç½®äºä¸ä¸ªè¡°å代ç ï¼
setInterval(function () {
// Make sure the playback rate never falls below .4
if (redQueen_alice.playbackRate > 0.4) {
redQueen_alice.playbackRate *= 0.9;
}
}, 3000);
使¯éè¿ç¹å»æç¹å»æ¥æ¦ä¿ä»ä»¬ä½¿ä»ä»¬éè¿ä¹ä»¥ææ¾é度æ¥å å¿«é度ï¼
const goFaster = () => {
redQueen_alice.updatePlaybackRate(redQueen_alice.playbackRate * 1.1);
};
document.addEventListener("click", goFaster);
document.addEventListener("touchstart", goFaster);
èæ¯å ç´ è¿å ·æææ¾æ¶é´ï¼å½ä½ ç¹å»æç¹å»æ¶ï¼å®ä»¬ä¼åå°å½±åãå½ Alice å Red Queen è·ä¸¤åçæ¶åä¼åçä»ä¹ï¼å½ä½ 让ä»ä»¬æ¾æ ¢æ¶ä¼åçä»ä¹ï¼
è·åå¨ç»ä¿¡æ¯
æ³è±¡å
¶ä»æ¹å¼æä»¬å¯ä»¥ä½¿ç¨ playbackRateï¼ä¾å¦éè¿è®©ä»ä»¬åæ
¢æ´ä¸ªç½ç«çå¨ç»æ¥æ¹åå
·æååºéç¢çç¨æ·çæ éç¢ãè¿ä¸å¯è½å¨ CSS ä¸éæ°è®¡ç®æ¯ä¸ª CSS è§åçæç»æ¶é´ï¼ä½æ¯éè¿ Web å¨ç» APIï¼æä»¬å¯ä»¥ä½¿ç¨å³å°å°æ¥çï¼å¨æµè§å¨ä¸ä¸æ¯æï¼ï¼document.getAnimations()æ¹æ³ 循ç¯éå页é¢ä¸çæ¯ä¸ªå¨ç»ï¼å¹¶å°å®ä»¬çææ¾é度ååï¼
document.getAnimations().forEach(function (animation) {
animation.playbackRate *= 0.5;
});
ä½¿ç¨ Web å¨ç» APIï¼ä½ éè¦æ´æ¹çåªæ¯ä¸ä¸ªå°ç屿§ï¼
å¦ä¸ä»¶ä¸ CSS å¨ç»æå ³çé¾ç¹å°±æ¯å建ä¾èµäºå ¶ä»å¨ç»æä¾çå¼ãä¾å¦ï¼å¨âæé¿åæ¶ç¼©ç±ä¸½ä¸â游æçä¾åä¸ï¼ä½ å¯è½ä¼æ³¨æå°èç³çæç»æ¶é´æäºå¥æªï¼
document.getElementById("eat-me_sprite").animate([], {
duration: aliceChange.effect.timing.duration / 2,
});
è¦äºè§£è¿éåçäºä»ä¹ï¼è®©æä»¬æ¥çç Alice çå¨ç»ï¼
const aliceChange = document
.getElementById("alice")
.animate(
[
{ transform: "translate(-50%, -50%) scale(.5)" },
{ transform: "translate(-50%, -50%) scale(2)" },
],
{
duration: 8000,
easing: "ease-in-out",
fill: "both",
},
);
ç±ä¸½ä¸çå¨ç»è®©å¥¹çå°ºå¯¸å¨ 8 ç§å ä»ä¸åå°ä¸¤åãç¶åæä»¬æå她ï¼
aliceChange.pause();
妿æä»¬å¨å¨ç»å¼å§æ¶å·²ç»æå¥¹æåäºï¼é£ä¹å¥¹çå
¨é¨å°ºå¯¸å°ä»ä¸åå¼å§ï¼å°±åå¥¹å·²ç»ææ´ä¸ªç¶åé½åå®äºä¸æ ·ï¼æä»¬æ³æå¨ç»çâææ¾å¤´âæ¾å¨ä¸é´ï¼è¿æ ·å¥¹å°±å¨åéäºãæä»¬å¯ä»¥éè¿å°å¥¹ç Animation.currentTime 设置为 4 ç§ï¼å¦ä¸æç¤ºï¼
aliceChange.currentTime = 4000;
使¯å¨å¶ä½è¿ä¸ªå¨ç»çæ¶åï¼æä»¬å¯è½ä¼æ¹åç±ä¸½ä¸çæç»æ¶é´ã妿æä»¬å°å¥¹ç currentTime è®¾ç½®ä¸ºå¨æçï¼å®ä¸ä¼æ´å¥½åï¼æä»¥æä»¬ä¸å¿
䏿¬¡åä¸¤ä¸ªæ´æ°ï¼æä»¬å®é
ä¸å¯ä»¥éè¿å¼ç¨ aliceChange ç Animation.effect 屿§æ¥å®ç°ï¼è¯¥å±æ§è¿åä¸ä¸ªå
å« Alice ä¸ææææç»èç对象ï¼
aliceChange.currentTime = aliceChange.effect.timing.duration / 2;
effect 让æä»¬è½å¤è®¿é®å¨ç»çå
³é®å¸§åæ¶é´å¯¹è±¡ââaliceChange.effect.timing æå Alice çæ¶é´å¯¹è±¡ï¼å
¶ç±»å为 AnimationEffectTimingReadOnlyï¼ââè¿å
å«å¥¹ç AnimationEffectTimingReadOnly.durationãæä»¬å¯ä»¥å°å¥¹çæç»æ¶é´åæä¸¤åï¼ä»¥è·å¾å¥¹å¨ç»æ¶é´è½´çä¸ç¹ï¼ä½¿å¥¹æä¸ºæ£å¸¸çé«åº¦ãç°å¨ï¼æä»¬å¯ä»¥å¨ä»»ä½ä¸ä¸ªæ¹åæè½¬åææ¾å¨ç»ï¼ä½¿å¥¹åå°æå大ï¼
å½è®¾ç½®èç³åç¶åçæç»æ¶é´æ¶ï¼æä»¬å¯ä»¥ååæ ·çäºæ ï¼
const drinking = document
.getElementById("liquid")
.animate([{ height: "100%" }, { height: "0" }], {
fill: "forwards",
duration: aliceChange.effect.getComputedTiming().duration / 2,
});
drinking.pause();
ç°å¨ï¼ææä¸ä¸ªå¨ç»åªæä¸ä¸ªæç»æ¶é´ï¼æä»¬å¯ä»¥ä»ä¸ä¸ªå°æ¹å®¹æå°æ¹åã
æä»¬è¿å¯ä»¥ä½¿ç¨ Web å¨ç» API æ¥ç¡®å®å¨ç»å½åçæ¶é´ãå½ä½ ç¨å°½èç³åæè
æ¸
空ç¶åæ¶ï¼æ¸¸æå°±ç»æäºãåªä¸ªè§è²æ®æ¼è
åå³äºç±ä¸½ä¸å¨å¥¹çå¨ç»ä¸æå¤è¿ï¼æ 论她æ¯å¦åå¾å¤ªå¤§ï¼ä¸è½è¿å
¥å°é¨å¤ªå°ï¼æ æ³è¾¾å°æå¼é¨çé¥åãæä»¬å¯ä»¥å¼æ¸
æ¥å¥¹æ¯å¦å¨å¨ç»ç大端æå°ç«¯ï¼è®©å¥¹çå¨ç»å½åæ¶é´ (currentTime) 被她ç activeDuration åæï¼
const endGame = () => {
// get Alice's timeline's playhead location
const alicePlayhead = aliceChange.currentTime;
const aliceTimeline = aliceChange.effect.getComputedTiming().activeDuration;
// stops Alice's and other animations
stopPlayingAlice();
// depending on which third it falls into
const aliceHeight = alicePlayhead / aliceTimeline;
if (aliceHeight <= 0.333) {
// Alice got smaller!
// â¦
} else if (aliceHeight >= 0.666) {
// Alice got bigger!
// â¦
} else {
// Alice didn't change significantly
// â¦
}
};
夿³¨ï¼getAnimations() and effect are not fully supported as of this writing, but the polyfill does support them today.
åè°å promise
CSS å¨ç»åè½¬æ¢æèªå·±çäºä»¶ä¾¦å¬å¨ï¼è¿äºä¹å¯ä»¥éè¿ Web å¨ç» APIï¼
onfinishis the event handler for thefinishevent and can be triggered manually withfinish().oncancelis the event handler for thecancelevent and can be triggers withcancel().
å¨è¿éï¼æä»¬ä¸ºèç³ï¼ç¶ååç±ä¸½ä¸è®¾ç½®åè°æ¥è§¦å endGame åè½ï¼
// When the cake or runs out...
nommingCake.onfinish = endGame;
drinking.onfinish = endGame;
// ...or Alice reaches the end of her animation
aliceChange.onfinish = endGame;
Prefer promises? The Web Animations API also specifies two promises: onfinish and oncancel.
夿³¨ï¼These promises are not fully supported as of this writing.
ç»è®º
è¿äºæ¯ Web å¨ç» API çåºæ¬åè½ï¼å ¶ä¸å¤§é¨ååè½å·²å¨ææ°çæ¬ç Firefox å Chrome ä¸å¾å°æ¯æãå°ç®å为æ¢ï¼ä½ åºè¯¥åå¤å¥½å¨æµè§å¨ä¸âè·³ä¸å åæ´âï¼å¨ç»å¶ä½å¨ç»å®éªï¼å¦æä½ æ£å¨ä½¿ç¨ API å¹¶è¦å ±äº«ï¼è¯·å°è¯ä½¿ç¨#WAAPI 䏻颿 ç¾ãæä»¬å°ä¼è§çå¹¶ä¸å°ç¼åæ´å¤çæç¨æ¥æ¶µçæ´å¤çåè½ï¼æ¯æä¼ æï¼
åè§
- The full suite of Alice in Wonderland demos on CodePen for you to play with, fork, and share
- Animating like you just donât care with Element.animate â a great article to read that explains more on the background of the Web Animations API, and why it is more performant than other web animation methods
- web-animations-js â the Web Animations API polyfill


