いつのまにか四月が過ぎていった。暑さはないものの、日差しの強さは日毎に増すばかり。近所のツツジも開きつつある。私はどうかというと、特になにも変わらない。コードを書いている。
フィヨルドブートキャンプでのプラクティスもポートフォリオ作りに入ってきた。作ろうとしているアプリのデモ版をつくっている。最小限のところをやって、本当に実現可能かを見極めるのだ。今回はアニメーションを追加する。
anime.js の導入
アニメーションの実装は anime.js というライブラリを利用する。
anime.js • JavaScript animation engine
なんでもできそう。
Rails 7より、JavaScriptの構築にimport mapsを使うことがデフォルトになった。それをつかってみる。コマンドを打つ。
$ ./bin/importmap pin animejs
これでパッケージを追加できた。
JavaScriptファイルを追加
既存のJavaScriptファイルとは別に、新しいファイルを追加する。そしてそこにanime.jsをimportする。
app/javascript/simurate.js
import anime from "animejs"; // 略
app/views/layouts/application.html.erb
<!DOCTYPE html> <html> <head> <! --略 --> <%= javascript_import_module_tag "simurate" %> </head> <body> <%= yield %> </body> </html>
このように、javascript_import_module_tag
とするとそのようになる。
参考:
GitHub - rails/importmap-rails: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.
svgを描く
<svg id="svg01" width="300" height="200" xmlns="http://www.w3.org/2000/svg"> <path d="M 0 60 H 100" /> </svg>
こうするとパスが描ける。パスは軌道であるので、目には見えない。これに沿ってアニメーションをしていけばいいのだな。
コードたち
viewファイルは以下のように書く。ボタンを押すと顔文字が動くようにしよう。
app/views/simurates/index.html.erb
<%= button_tag 'Start', {id: "startbutton"} %> <div class="svg-wrapper"> <div id="ob1">(゜∀゜)</div> <div id="ob2">(つ´∀`)つ</div> <svg id="svg01" xmlns="http://www.w3.org/2000/svg" width="1000" height="500"> <path fill=none stroke="red" d="M 0 0 L 200 300 L 20 300 Z"/> </svg> </div>
app/javascript/simurate.js
import anime from "animejs"; function animeStart() { const path = anime.path("#svg01 path"); let object1 = { targets: "#ob1", translateX: path("x"), translateY: path("y"), direction: "alternate", duration: 4000, loop: true, easing: "linear", }; let object2 = { targets: "#ob2", translateX: path("x"), translateY: path("y"), direction: "alternate", duration: 4000, loop: true, easing: "easeInOutSine", }; var tl = anime.timeline({ easing: "easeOutExpo", duration: 500, }); tl.add(object1).add(object2, "-=2000"); } document.addEventListener("DOMContentLoaded", () => { const start = document.getElementById("startbutton"); if (start) { start.addEventListener("click", animeStart(), false); } });
スタイルシートはこんな感じ。
#ob1, #ob2 { position: absolute; top: -15px; left: -25px; } .svg-wrapper { margin: 24px; position: relative; }
うごく
https://www.youtube.com/watch?v=mAKYW_1f-dw
ここの動画が役に立った