はじめに
これはCyberAgent 20新卒 Advent Calendar 2019の7日目の記事です!
クリスマスが待ち遠しいですね🎅今回はWebフロントでクリスマスっぽい何かを作っていきたいと思います💪
前置き
今回はFramerMotionと言うReactのアニメーションライブラリを使ってみたいと思います!
FramerMotionとは
FramerMotionはReactのDesign系のライブラリで、リッチなアニメーションを簡単に作ることが出来ます。
import { motion } from "framer-motion"
export const MyComponent = () => (
<motion.div
animate={{ scale: 2 }}
transition={{ duration: 0.5 }}
/>
)
記法はこのようになっていて、アニメーションの目的地点をanimateに、そこまでの流れをtransitionに記述することで作動します。FramerMotionではmotion.div
のようなHTMLの要素に加え、motion.svg
でsvgに対しても簡単にアニメーションを付与することが可能です!
指定可能なanimationの参考
https://www.framer.com/api/motion/component/#supported-values
指定可能なtransitionの参考
https://www.framer.com/api/motion/types/#transition
作業内容
概要
今回はFramerMotionのsvgアニメーションに着目して、svgでクリスマスツリーのアニメーションを作ってみたいと思います!それでは順番に解説していきます!
手順
- イラストをSVGで書き出す
- Reactプロジェクト作成とSVGの埋め込み
- FramerMotionでアニメーションをつける
(Option: 雪を降らせる❄️)
1. イラストをSVGで書き出す
SVGは座標指定することで図形を描画できます。
参考
https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Paths
ですが、複雑な図形を作るのは大変なので、Drawingソフトで図形を描き、自動でSVGをエクスポートします。今回は、無料で使えるVectrを使って作成しました!
🚨デザインは一筆書きで作ります。
2. Reactプロジェクト作成とSVGの埋め込み
プロジェクト作成
FramerMotionはReact用のDesignライブラリなので、Reactのプロジェクトを新規で作成します。今回はcreate-react-app
を使ってサクッと立ち上げていきます!
// Reactプロジェクト作成
$ yarn create react-app merry-xmas
// framer-motionの追加
$ yarn add framer-motion
今回は
- ツリーてっぺんの星
- 木の部分(緑色)
- 幹の部分(茶色)
でパーツを作って組み合わせます。
SVG埋め込み
1.でエクスポートした.svgのファイルをVSCodeなどで開くと、<path d="M...Z">
が見つかると思います。この" "
で囲まれた中をFramerMotionの<motion.path>
に記述することで、線画のアニメーションが可能となります👍
// 木の部分(緑色)
<motion.path
className="tree-body-stroke"
d="M140.93 32.47L154.78 49.39L168.57 66.88L177.28 76.47L147.28 76.47L156.16 90.01L167.44 103.9L183.23 123.85L199.78 140.21L213.13 150.93L177.28 150.93L184.78 164.46L197.9 182.65L217.08 205.15L234 222L0.48 222L19.78 202.26L42.28 174.05L58.57 150.93L21.35 150.93L32.63 141.9L46.73 127.8L63.09 108.62L76.06 92.65L87.28 75.91L57.28 75.91L73.8 57.29L88.47 38.11L117.28 -0.24L140.93 32.47Z"
variants={body}
initial="hidden"
animate={isVisible ? "visible" : "hidden"}
/>
上記のvariants
はより柔軟なアニメーションの指定ができる仕組みだと思います。
const body = {
hidden: {
// animateの内容
opacity: 0,
pathLength: 0,
fill: "rgba(2, 135, 96, 0)",
// transitionの内容
transition: {
duration: 3.3,
ease: "anticipate",
fill: { duration: 3.5 }
}
},
visible: {
opacity: 1,
pathLength: 1,
fill: "rgba(2, 135, 96, 1)",
transition: {
duration: 2,
ease: "easeInOut",
fill: { duration: 3 }
}
}
};
こんな感じでanimateとtransitionを個別の条件ごとに定義できます。
3. FramerMotionでアニメーションをつける
今回は
- Springによるアニメーション
- ドローのアニメーション
の2つを作っていきます。
Springによるアニメーション
Springとは、バネのような物理的な挙動を模したアニメーションです。他のライブラリだとreact-springが有名です。
今回はこれで、左右にバウンドする星を作ってみたいと思います!
<motion.svg
xmlns="https://www.w3.org/2000/svg"
viewBox="0 0 50 50"
initial={{ rotate: 0 }}
animate={{
rotate: [-45, 40, -35, 30, -25, 20, -15, 10, -5, 3, -2, 1, 0]
}}
transition={{
delay: 1.5,
type: "spring",
loop: Infinity,
repeatDelay: 2,
duration: 1.3
}}
>
徐々に減衰していく運動を、今回は簡単にrotate
を減少させる形で実現しました。これでプルプル揺れるお星様の完成です⭐️
ドローのアニメーション
SVGは座標をつなぎ合わせて図形を描画しており、このつなぎ合わせる部分をアニメーションにすることが出来ます!今回はこれで、ツリーの外形が徐々に作られていく様子をアニメーションにしたいと思います。
const body = {
hidden: {
pathLength: 0,
fill: "rgba(2, 135, 96, 0)",
...
},
visible: {
pathLength: 1,
fill: "rgba(2, 135, 96, 1)",
....
}
};
pathLength
が1で全ての点が結合された(図形が描画された)状態になります。
fill
で枠の内側の着色を指定できます。
完成
最終的に出来上がったものがこちらになります🎄
メリークリスマスイブ×18日
まとめ
今回初めてAdventCalendarに投稿させていただきましたが、固すぎず緩すぎず、ちょうど良い温度感で取り組めたのが良かったなと思っています!お誘いいただきありがとうございました👍
自分はデザインの方面にも興味があるので、今後もこうしたデザイン系の情報をキャッチアップしていければなと思います!
最後に
☃️雪はparticle.jsで描画しています❄️