SVGアニメーション – Web Animations API を使う – アニメーション実行中にKeyFrameEffectのcompositeプロパティを変更した場合の挙動について
アニメーション実行中にKeyFrameEffectのcompositeプロパティをスクリプトから変更することができます。
compositeプロパティはアニメーションのkeyframeの複数の項目がある場合、
その複数の項目の値をどのように設定するかを制御します。
例えばdivが画面上に2つある場合、一つをDivAとし、もう一つをDivBとする場合、
DivAに設定されたkeyframeの項目とDivBに設定されたkeyframeの項目の値をどのようにするかを制御します。
ここでは「DivA」と「DivB」をもとに掘り下げてみます。
ボタンは「add」「accumulate」「replace」3種類あり、それぞれ以下の挙動になります。
①add
DivAとDivBのkeyframeのプロパティを加算(合算)します。
例えばDivAに、以下のkeyframeが設定されており、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(150px)'}, ];
DivBに、以下のkeyframeが設定されている場合、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
addした結果は以下のようになります。
[ {transform: 'translateX(0px)' }, {transform: 'translateX(150px)'}, {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
②accumulate
DivAとDivBのkeyframeのプロパティを累積します。
例えばDivAに、以下のkeyframeが設定されており、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(150px)'}, ];
DivBに、以下のkeyframeが設定されている場合、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
addした結果は以下のようになります。
[ {transform: 'translateX(0px)' }, {transform: 'translateX(350px)'}, ];
③replace
DivAとDivBのkeyframeのプロパティを上書き(置き換え)します。
例えばDivAに、以下のkeyframeが設定されており、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(150px)'}, ];
DivBに、以下のkeyframeが設定されている場合、
[ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
replaceした結果は以下のようになります。
[ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
(注意…説明では②accumulateと同じ値になりますが、プロパティがtranslateXのみで、2項目しかないので見かけ上は同様になります)
上記にまとめた挙動を確認する為
画面上のボタン押下によってアニメーション再生中にcompositeプロパティを動的に変更した時の動きを確認できるサンプルを用意しました。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>テストHTML</title> <style> #bottomStart { margin-bottom : 10px; } #pseudoElementTest1 { color : #5f5d5d; background-color : #ffdfdf; font-size : 1.1rem; width : 100px; } #pseudoElementTest2 { color : #5f5d5d; background-color : #f4f4f4; background-color : #dfe7ff; font-size : 1.1rem; width : 100px; } </style> </head> <body> <!-- 開始ボタン --> <div id="bottomStart"> <input type="button" id="animate_timline_test" value="アニメーション開始"> </div> <!-- 変更ボタン --> <input type="button" id="set_composite_add" value="addに変更"> <input type="button" id="set_composite_accumulate" value="accumulateに変更"> <input type="button" id="set_composite_replace" value="replaceに変更"> <!-- 状態 --> <div>現在の状態:<span id="pseudoElementDisp"></span></div> <!-- アニメーション用DIV --> <div id="pseudoElementTest1">TEST1</div> <div id="pseudoElementTest2">TEST2</div> <script> //-------------------------------- // DOM要素取得 //-------------------------------- let animateTimlineTestDom = document.querySelector("#animate_timline_test"); let pseudoElementTest1Dom = document.querySelector("#pseudoElementTest1"); let pseudoElementTest2Dom = document.querySelector("#pseudoElementTest2"); let pseudoElementDispDom = document.querySelector("#pseudoElementDisp"); // プロパティ変更ボタン let dom_set_composite_add = document.getElementById('set_composite_add'); let dom_set_composite_accumulate = document.getElementById('set_composite_accumulate'); let dom_set_composite_replace = document.getElementById('set_composite_replace'); //-------------------------------- // アニメーション用定義 //-------------------------------- // アニメーション用オブジェクト let animation1; let animation2; // keyframesの定義 const keyframes1 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(150px)'}, ]; const keyframes2 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ]; // アニメーション開始ボタン animateTimlineTestDom.addEventListener('click', (e) => { // デフォルトはaddにする updateanimation('add'); }, false); // 「addに変更」 dom_set_composite_add.addEventListener('click', () => { updateanimation('add'); }, false); // 「accumulateに変更」 dom_set_composite_accumulate.addEventListener('click', () => { updateanimation('accumulate'); }, false); // 「replaceに変更」 dom_set_composite_replace.addEventListener('click', () => { updateanimation('replace'); }, false); // 引数に基づいたアニメーションの開始 function updateanimation(upd_composite) { // 画面表示 pseudoElementDispDom.innerHTML = upd_composite; // optionの定義 const currentOptions1 = { duration : 15000, iterations : Infinity }; const currentOptions2 = { duration : 15000, iterations : Infinity, composite : upd_composite // このタイミングでcompositeの値を更新 }; // オプションを設定する animation1 = pseudoElementTest1Dom.animate(keyframes1, currentOptions1); // オプションを設定する animation2 = pseudoElementTest2Dom.animate(keyframes2, currentOptions2); // アニメーション開始 animation1.play(); animation2.play(); } </script> </body> </html>
画面にアクセスして「アニメーション開始」を押下します。
すると、画面上の2つのdivタグがアニメーションします。
アニメーション中に「addに変更」「accumulateに変更」「replaceに変更」のいずれかのボタンを押下すると、
2つめのDiv「TEST2」のcompositeプロパティの値が動的に変化します。
「アニメーション開始」ボタン押下後、addに変更ボタンを押下するとDivタグ「pseudoElementTest2」のcurrentOptions2プロパティが変わり、
const keyframes2 = [ {transform: 'translateX(0px)' }, {transform: 'translateX(200px)'}, ];
のプロパティの値が動的に変わる(この場合は項目の加算)ことがわかります。
また、「accumulateに変更」ボタン、「replaceに変更」ボタンを押下した時も同様に変化することがわかります。
さらに、アニメーション中に「accumulateに変更」ボタンをN回押下するとプロパティが更新された後、
また「accumulateに変更」ボタンを押下すると値が累積してアニメーションすることがわかります。
この場合はtranslateXの値がN回押下分累積した値になることがわかります。