SVGアニメーション – Web Animations API を使う – アニメーションのfinish、cancel、removeイベントについて
前回までの投稿でanimationのplayStateプロパティでアニメーション中の状態(idle、running、paused、finished、pending)を取得することができました。
例
// アニメーションが再生中の場合に秒数を更新 if (animation1.playState === 'running') {
ここではアニメーションが終了、停止、削除された時のイベントについて、試してみます。
finish()イベント
アニメーションが終了した時に呼ばれるイベント
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>テストHTML</title> <style> #bottom { margin-bottom : 10px; } #test1_dom { color : #5f5d5d; background-color : #cccccc; font-size : 1.1rem; width : 150px; } </style> </head> <body> <!-- ボタン --> <div id="bottom"> <input type="button" id="start_animate" value="アニメーション開始"> </div> <!-- アニメーション用DIV --> <div id="test1_dom">TEST1 (<span id="display"></span>)</div> <!-- 再生秒数 --> <div class="params" id="currentTime_value"></div> <script> // DOM要素取得 let start_animate_dom = document.querySelector("#start_animate" ); let cancel_animate_dom = document.querySelector("#cancel_animate"); let display_dom = document.querySelector("#display" ); let test1_dom = document.querySelector("#test1_dom" ); // アニメーション用定義 let animation1; // keyframes定義 const keyframes1 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(500px)'}, ]; // option定義 const options1 = { duration : 3000 }; animation1 = test1_dom.animate(keyframes1, options1); animation1.cancel(); // 初期値は停止 // アニメーション開始 start_animate_dom.addEventListener('click', (e) => { // 開始ボタン押下でスライダ移動した挙動を同じ動きをする animation1.play(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション終了時のイベント(注:domではなくanimateのインスタンスに対してのイベント付与) animation1.addEventListener('finish', (e) => { // finish時にアラート alert("animation finish !"); display_dom.innerHTML = animation1.playState; }, false); // 再生秒数を定期的に更新する setInterval(() => { // アニメーションが再生中の場合に秒数を更新 if (animation1.playState === 'running') { // currentTimeはミリ秒で返されるので、秒に変換して表示 let disp_sec = (animation1.currentTime / 1000).toFixed(2) + '秒'; document.getElementById('currentTime_value').innerHTML = disp_sec; } }, 10); // 0.01秒ごとにチェック </script> </body> </html>
サンプル画面のアニメーション開始を実行し、アニメーションが終わるとアラートが表示されます。
その際「animation1.addEventListener(‘finish’, (e) => {」で記述したfinishのイベントリスナが呼ばれることがわかります。
cancel()イベント
アニメーションがidel状態に入った時に呼ばれるイベント
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>テストHTML</title> <style> #bottom { margin-bottom : 10px; } #test1_dom { color : #5f5d5d; background-color : #eeeeee; font-size : 1.1rem; width : 150px; } </style> </head> <body> <!-- ボタン --> <div id="bottom"> <input type="button" id="start_animate" value="アニメーション開始" > <input type="button" id="pause_animate" value="アニメーション一時停止"> <input type="button" id="reverse_animate" value="アニメーション逆再生" > <input type="button" id="finish_animate" value="アニメーション終了" > <input type="button" id="cancel_animate" value="アニメーション停止" > </div> <!-- アニメーション用DIV --> <div id="test1_dom">TEST1 (<span id="display"></span>)</div> <!-- 再生秒数 --> <div class="params" id="currentTime_value"></div> <script> // DOM要素取得 let start_animate_dom = document.querySelector("#start_animate" ); let pause_animate_dom = document.querySelector("#pause_animate" ); let reverse_animate_dom = document.querySelector("#reverse_animate"); let finish_animate_dom = document.querySelector("#finish_animate" ); let cancel_animate_dom = document.querySelector("#cancel_animate" ); let display_dom = document.querySelector("#display" ); let test1_dom = document.querySelector("#test1_dom" ); // アニメーション用オブジェクト let animation1; // keyframes定義 const keyframes1 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ]; // option定義 const options1 = { duration : 3000 }; animation1 = test1_dom.animate(keyframes1, options1); animation1.cancel(); // 初期値は停止 // アニメーションキャンセル時のイベント(注:domではなくanimateのインスタンスに対してのイベント付与) animation1.addEventListener('cancel', (e) => { // cancel時にアラート alert("animation cancel !"); display_dom.innerHTML = animation1.playState; }, false); // アニメーション開始 start_animate_dom.addEventListener('click', (e) => { animation1.play(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション一時停止 pause_animate_dom.addEventListener('click', (e) => { animation1.pause(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション逆再生 reverse_animate_dom.addEventListener('click', (e) => { animation1.reverse(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション終了 finish_animate_dom.addEventListener('click', (e) => { animation1.finish(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション停止 cancel_animate_dom.addEventListener('click', (e) => { animation1.cancel(); display_dom.innerHTML = animation1.playState; }, false); // 再生秒数を定期的に更新する setInterval(() => { // アニメーションが再生中の場合に秒数を更新 if (animation1.playState === 'running') { // currentTimeはミリ秒で返されるので、秒に変換して表示 let disp_sec = (animation1.currentTime / 1000).toFixed(2) + '秒'; document.getElementById('currentTime_value').innerHTML = disp_sec; } }, 10); // 0.01秒ごとにチェック </script> </body> </html>
画面にアクセスし「アニメーション終了」ボタンを押下したとき、
「animation1.addEventListener(‘cancel’, (e) => {」のイベントリスナが呼ばれていることがわかります。
remove()イベント
アニメーションが削除された時に呼ばれるイベント
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>テストHTML</title> <style> #bottom { margin-bottom : 10px; } #test1_dom { color : #5f5d5d; background-color : #eeeeee; font-size : 1.1rem; width : 150px; } </style> </head> <body> <!-- ボタン --> <div id="bottom"> <input type="button" id="start_animate" value="アニメーション開始" > <input type="button" id="pause_animate" value="アニメーション一時停止"> <input type="button" id="reverse_animate" value="アニメーション逆再生" > <input type="button" id="finish_animate" value="アニメーション終了" > <input type="button" id="cancel_animate" value="アニメーション停止" > <input type="button" id="remove_animate" value="手動削除" > </div> <!-- アニメーション用DIV --> <div id="test1_dom">TEST1 (<span id="display"></span>)</div> <!-- 再生秒数 --> <div class="params" id="currentTime_value"></div> <script> // DOM要素取得 let start_animate_dom = document.querySelector("#start_animate" ); let pause_animate_dom = document.querySelector("#pause_animate" ); let reverse_animate_dom = document.querySelector("#reverse_animate"); let finish_animate_dom = document.querySelector("#finish_animate" ); let cancel_animate_dom = document.querySelector("#cancel_animate" ); let remove_animate_dom = document.querySelector("#remove_animate" ); let display_dom = document.querySelector("#display" ); let test1_dom = document.querySelector("#test1_dom" ); // アニメーション用オブジェクト let animation1; // keyframes定義 const keyframes1 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ]; // option定義 const options1 = { duration : 3000 }; animation1 = test1_dom.animate(keyframes1, options1); animation1.cancel(); // 初期値は停止 // アニメーションキャンセル時のイベント(注:domではなくanimateのインスタンスに対してのイベント付与) animation1.addEventListener('remove', (e) => { // remove時にアラート alert("animation remove !"); display_dom.innerHTML = animation1.playState; }, false); // アニメーション開始 start_animate_dom.addEventListener('click', (e) => { animation1.play(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション一時停止 pause_animate_dom.addEventListener('click', (e) => { animation1.pause(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション逆再生 reverse_animate_dom.addEventListener('click', (e) => { animation1.reverse(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション終了 finish_animate_dom.addEventListener('click', (e) => { animation1.finish(); display_dom.innerHTML = animation1.playState; }, false); // アニメーション停止 cancel_animate_dom.addEventListener('click', (e) => { animation1.cancel(); display_dom.innerHTML = animation1.playState; }, false); // 手動削除 remove_animate_dom.addEventListener('click', (e) => { // removeイベントを発火する const removeEvent = new Event('remove'); animation1.dispatchEvent(removeEvent); // 手動でremoveイベントを発生させる // 要素を削除する test1_dom.remove(); display_dom.innerHTML = animation1.playState; }, false); // 再生秒数を定期的に更新する setInterval(() => { // アニメーションが再生中の場合に秒数を更新 if (animation1.playState === 'running') { // currentTimeはミリ秒で返されるので、秒に変換して表示 let disp_sec = (animation1.currentTime / 1000).toFixed(2) + '秒'; document.getElementById('currentTime_value').innerHTML = disp_sec; } }, 10); // 0.01秒ごとにチェック </script> </body> </html>
画面にアクセスして「手動削除」ボタンを押下すると、
「remove_animate_dom.addEventListener(‘click’, (e) => {」のイベントリスナ内で、
animation1のオブジェクトに対してremoveイベントを発火させています。
// removeイベントを発火する const removeEvent = new Event('remove'); animation1.dispatchEvent(removeEvent); // 手動でremoveイベントを発生させる
なぜこの方法をとるかというと、animation1のオブジェクトを直接
animation1.remove()
という形で削除メソッドを実行しても「animation1オブジェクトはremoveメソッドを持たない」為にエラーになります。
なので、new Eventでremoveイベントを定義し、それをdispatchEventすることによって
animation1オブジェクトを削除しています。
削除時の挙動としては「animation1.addEventListener(‘remove’, (e) => {」で定義したremoveのイベントハンドラが実行されアラートが表示されることがわかります。
その後、明示的にDOM要素を削除していますが、
// 要素を削除する test1_dom.remove();
この削除命令がなくてもanimation1のremoveイベントハンドラは実行される点に注意が必要です。