SVGアニメーション – Web Animations API を使う – アニメーションのfinish、cancel、removeイベントについて

javascript

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>

サーバ上のHTMLはこちら(test1.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>

サーバ上のHTMLはこちら(test2.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>

サーバ上のHTMLはこちら(test3.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イベントハンドラは実行される点に注意が必要です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です