JavaScript で keyframes の登録と Web Animations API
Page No.1
ちょっと必要になって思ったことなのだけれど、ページのロードが終わってから、JavaScript で CSS animation の @keyframes の生成というか登録はどうやるのだろうかと。
CSSStyleSheet.insertRule
まず、やってみたのは既存のロード済みのスタイルシートに追加する方法。でも、どこかが間違っているのかこの方法ではうまくいかなかった。
で、次にやってみたのが以下の、新規に 生成した ”style” に登録する方法。こちらはちゃんと機能した。
2つの keyframes を登録してる。ちなみに keyframes だけじゃなくて、普通の css のプロパティも当然可能。
関数自体は実に簡単なもの。
insertRule の詳細はこちらをご覧あれ → CSSStyleSheet.insertRule()
8行目のコメントアウトしてある type を指定する文は、参考にさせていただいた元のページにあったものだけれど、VScode に「非推奨」とのことで否定線を引かれてしまう。試しにコメントアウトしてみたが、この文は無くても問題なく機能してくれた。
insertRule() の2つ目の引数は、挿入する場所の指定。0 なら先頭に、dynamicStyles.length は最後に挿入するということ。
とりあえず作ったとき、16行目からの keyframes の指定の文字列のように、わかりやすいように改行をつけるために、従来のES5でクォートと+を使って書いていた。が、実際に IE11 で試してみたところ、それでも結局動かなかったので、あえてES5で書く必要は全くなく、31行目からのようにES6のバッククォートを使った書き方なら、実に手間いらずで CSS からそのまま貼り付けるだけですむ。
※注:後日、違うところで普通のスタイル設定をES5で書いてやっていたらIE11でも動いているので、keyframes でなければ、ということのようである。
いやいや違う違う、keyframes でも動きました。ということなので、ES5 で書けば IE11 でも動いてます。と・・・、なぜ初めにやったときは動かなかったのだろう。どこか他にエラーがあったのでしょうね。なんのことやら。
上にも書いたけれど、もちろん普通の css のプロパティも可能なんだけれど、ただ、複数の要素に対してのスタイルの登録に関して、全部まとめて一気にということはできないよう。実際にあれこれやってみたがエラーとなってしまいうまくいかなかった。こういう場合は一つの要素づつ、関数を呼んでやればうまくいった。下のような具合に。
Web Animations API
ところで、別のやり方として Web Animations API というものもあるとのこと。これを使えば JavaScript からアニメーションを設定したり、動作を制御したり、本格的にアニメーションを操作することができるってことである。
こんなのがちゃんとあったんだね~!って、知らなかったのかよっ!ってか!
いまはメジャーなブラウザなら対応してるよう。
使い方等、詳細はこちらをご覧あれ → Web Animations API を利用する
使うのは何も難しいことはなく、対象の要素にアニメーションの keyframes とその長さやら動きなどのオプションというかプロパティの設定を引数にして animate() を実行させるだけ。
CSS とは細かいところで色々と書き方が違ってる。
まず、keyframes において、CSS では動作のタイミングを ”from” とか ”%” で指定していたけれど、それは使わない。何も指定しなければ、ポイントの数で均等割、中間ポイントで50%。指定するなら ”offset:” を使って、たとえば、二行目を30%のタイミングに指定するなら、{ left: ‘5px’, offset: 0.3 } のようにする。
オプションにおける CSS 側との対応は以下のよう。
- javascript => CSS
- duration => animation-duration
- delay => animation-delay
- fill => animation-fill-mode
- iterations => animation-iteration-count
- direction => animation-direction
- easing => animation-timing-function
- iterationStart => なし
- endDelay => なし
CSS側にないもので、iterationStart と endDelay なるものがある。
これはそれぞれ・・・。
- iterationStart
- 英語の説明を読んでもよくわからなかったけれど、ちゃんと説明してくれてるサイトがちゃんとあるものです。
要は、keyframe のどこのポイントからアニメーションをスタートさせるかっていう設定。そしてそこから一周するわけ。途中から終わりまで行って最初に戻って始まったポイントの一つ前まで。0.5 を指定すれば 50%のポイントからスタートする。
これはいいね~、同じアニメーションで変化をつけたい時なんかにつかえそうだ。 - endDelay
これは繰り返し動作させてるときに、次のアニメーションの開始との間隔の設定だと思う。実はこれはこれまで何度も設定したい場面があったので、これもありがたい。
と、上のように思っていたのだけれど、実際にやってみたら違っていた。どうもアニメーションが終わったことを引き伸ばすためのものではなかろうか。そこまで確認はしなかったからよくわからないのだけど。- iterationComposite, composite
- あと iterationComposite と composite なんてのもあるけれど。
説明を読んだけれど、試したことがないせいかよくわからない。iterationComposite は、たぶんデフォルトではアニメーションを始めるたびに、変化させる価を元にもどして始めるのを、価をそのまま加算させて始めるかという設定だと思う。composite の方は、同時に動いている別のアニメーションで変化させる価を、両方の価を加算させるということだろうか。まぁ、実際にやってみればわかることなのだろうけれど・・・。
全く関係のないことだけれど、この記事をブロックエディタで書いていて気がついた。<dl>タグがないじゃないか。なんで?
と、すぐに innerblock を使って blockを作るということになったのである。
と、まぁ、それはおいといて。
- iterations : 繰り返し回数。default 1。繰り返しの “infinite” は、代わりに JavaScript の予約語である Infinity を使うというのがちょっと特殊なところ、予約語なのでうっかりクォートをつけないよう。
- duration と delay の単位は s(秒)ではなく ms
- direction : ‘normal’, ‘reverse’, ‘alternate’, ‘alternate-reverse’
- easing : ‘linear'(default), ‘ease’, ‘ease-in’, ‘ease-out’, ‘ease-in-out’, ‘cubic-bexier()’, ‘steps()’
- fill : ‘forwards’, ‘backwards’, ‘both’, default ‘none’
で、ちょっとここで easing に関しての注釈を。
easing 、css animation だと animation-timing-function ということなんだけれど、同じように使えば良いものと思い、実際に Javascript の方でも animation のプロパティの方へ指定してみたところ、全くもって意図したようには動いてくれなかった。css で意図したように動いていたものをそのまま移植したにもかかわらず。いったいこれはどういうことか?となかなか出口を見つけることができなかった。
で、今一度、ネットで確認したところ、「MDN WebDocs Keyframe Formats」 にその答えがしっかりと書いてあった。easing は keyframe の方で指定すればよかった。
そして、Web Animations API なら、一時停止や再生など、動作の制御もできるメソッドが用意されてる。
たとえば、下のように変数に入れておいて・・・。
- anim.pause()
- anim.play()
- anim.finish() :アニメーションの最後までスキップ。
- anim.cancel():アニメーションを中止し、そのエフェクトを削除。
- anim.reverse():Animation.playbackRate に負数を設定し、アニメーションの再生方向を逆方向にする。
という具合で使えるとのこと。
finish() においては、Infinity が設定してある animation ではエラーとなってしまい使えなかった( FireFox & chrome )。これは回数である数字を指定すれば使える。で、Infinity の場合、 cancel() が使えた。
そして実際に使ってみて便利だったのが、アニメーションの終了イベントハンドラーである、onfinish。javascript にはもともと css animation が終わったことのイベントとして、animationend というものがあるけれど、それだと全ての animation において引っかけてしまう。使いかたは、上の pause や finish と同じ。あと、oncancel の方もある。
私的には、その対象の animation が終わったら、click イベントと scroll イベントにて処理を指定という具合に使用した。
と、いうことでこれは便利なものがあった。
style に css を挿入なんてことはしていないで、これを使うべし!って感じですな。
Post : 2020/12/17 10:11
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=163407