デモを読み込み中...
スコアカード
| ライブラリ | 実装行数 | 使用API | 主観メモ |
|---|---|---|---|
| Anime.js | 18行 | animate / onScroll(sync,enter,leave) | 1つのAPIで全部できるが閾値記法に慣れが必要 |
| Motion | 16行 | scroll / inView / animate | 役割分担が明快で解除も関数呼び出しだけ |
コード比較
import { animate, onScroll } from "animejs";
// ScrollObserverをautoplayへ渡す設計。
// sync: true でスクロール量に同期(スクラブ)、省略すると閾値トリガー再生
animate(bar, {
scaleX: [0, 1],
ease: "linear",
autoplay: onScroll({
container,
target: inner,
enter: "top top",
leave: "bottom bottom",
sync: true,
}),
});
// 閾値トリガー(入場したら再生)
animate(box, {
x: 180,
rotate: 360,
autoplay: onScroll({ container, target: section }),
});
// 後始末: animation.revert() と observer.revert()import { animate, inView, scroll } from "motion";
// スクラブはscroll()にanimate()を包んで渡す。
// 対応ブラウザではScrollTimelineによりハードウェアアクセラレーションされる
const stopBar = scroll(
animate(bar, { scaleX: [0, 1] }, { ease: "linear" }),
{ container },
);
// 範囲指定はoffset("target視点 container視点"のペア)
const stopBox = scroll(animation, {
container,
target: section,
offset: ["start end", "end start"],
});
// 閾値トリガーはinView()。戻り値の関数が離脱時に呼ばれる
const stopCard = inView(card, (el) => {
animate(el, { opacity: [0, 1], y: [24, 0] }, { duration: 0.8 });
return () => {}; // leave時の処理
}, { root: container, amount: 0.5 });
// 後始末: stopBar() / stopBox() / stopCard() を呼ぶだけ- -Anime.jsはonScroll()が1つでスクラブ(sync)もトリガーも担う統合設計。enter/leaveの'bottom top'式の閾値記法は強力だが学習コストがある。
- -Motionはスクラブ=scroll()、トリガー=inView()と役割で関数が分かれており、どちらも戻り値の関数を呼ぶだけで解除できる。クリーンアップはMotionの方が単純。
- -Motionのscroll()は対応ブラウザでScrollTimeline(コンポジタ駆動)を使うため、メインスレッドが忙しくてもスクラブが滑らかに保たれやすい。