「専門スキルを伸ばす VS 幅広い領域に挑戦する」フリーランスの生存戦略討論
- スキル
- フリーランス/個人事業主
- 座談会
「Framer Motion」は、React.jsで使用できるオープンソースのアニメーションライブラリ。複雑なレイアウトを簡単にアニメーション化できる、とても優秀なライブラリです。
今回は、最先端のWebデザイン制作におすすめのFramer Motionの使いかたについて解説します。
目次
上記が今回制作するアニメーションです。
いろいろな要素が動いていますが、おもな構成要素は以下のとおり。
では、いよいよアニメーションを制作していきましょう。
白いカーテンを上下に引くようなこのアニメーションには、「カーテンを上げる」「カーテンを下げる」という2つの異なる動きが必要になるため、variantを使用します。
const alternateはvariantで、あとで使用できるアニメーションを複数保持しています。また、ベジェ曲線の標準的な表記方法を使って簡単に書けるように、transitionを定義しました。
export default function Curtain({ number }) {
const alternate = {
even: {
y: “100vh”,
transition: transition,
},
odd: {
top: 0,
y: “-100vh”,
transition: transition,
},
};
const transition= {
duration: 1,
ease: [1,.01,.49,1.05],
delay: 0.4
}
... other code ...
これで左端から数えて偶数のカーテンが下がり、奇数のカーテンが上がるというアニメーションができるようになります。
つぎは、これらにアニメーションを割り当てましょう。
return (
<motion.div
id="curtains">
{[…Array(number)].map((x, i) => (
<motion.div
animate = { i%2 == 0 ? “odd”: “even” }
className=”curtain”
variants={alternate}
></motion.div>
))}
</motion.div>
); // the return closing
} // the full function closing
これらはコピー&ペーストでOK。
このうち、numberは以下のような関数に渡す値です。
function Curtains({number}) {
return(“what we need”);
カーテンの枚数を決めるのに使う予定ですが、必須ではありません。
map関数のiを使って2で割った残りを計算し、偶数か奇数のどちらにあたるかを把握し、正しいvariantを割り当てます。
animate = { i%2 == 0 ? “odd”: “even” }
あとは必要なものは、スタイルだけ。
CSSだけでなく、motion.div内にinitialを使って直接指定することも可能です。
initial = {{ background: “white”, height: "100vw" }} // for example
こうすることで、インデックスと数学に基づいた特別なルールを定義できます。
CSSバージョンは以下のとおり。
#curtains { /* this is the container of all curtains */
width: 100vw;
position: absolute;
overflow: hidden;
top: 0;
left: 0;
}
.curtain { /* a single curtain */
background: white ;
borderRight: 1px rgb(247,247,247) solid;
height: 100vh;
width: 25vw; /* change if you want more columns */
float: left;
display: inline-block;
}
カーテンが動きまわったり、レイアウトが変わったりしないように、コンテナのoverflowをhiddenにしましょう。
最近のWebデザインでもよく見かける、下からニュッと現れるアニメーション。さまざまな場面で応用できるので、ぜひ参考にしてみてください。
ただ下から現れるのではなく、見えないブロックに切り取られているように見せたいので、overflowを活用します。
<span id=”overflower”>
<motion.h1
initial={{
opacity: 0,
y: “100%”,
}}
animate={{
opacity: 1,
y: 0,
transition: {
duration: 0.45, delay: 1.4, ease: “easeInOut”},
}}
>
photographer
</motion.h1>
</span>
タイトルには下から上に動くシンプルなアニメーションをつけました。
切り取りには以下のようにCSSを使っています。
#overflower {
display: block;
overflow: hidden;
}
#overflower h1 {
font-family: “Volux”;
color: white;
font-size: 80px;
position: relative;
width: 50%;
padding: 30px;
}
先ほどと同様の原理で、画像の動きにもvariantを使います。
画像のアニメーションは2種類。ひとつは画像が表示された際のアニメーション、もうひとつはホバー時のアニメーションです。
function Gallery() {
const hover = {
scaleX: 1.1,
scaleY: 1.1,
filter: “brightness(1)”,
transition: {
duration: 0.3,
ease: “linear”,
},
};
const zoom = {
initial: { scale: 1, x: -80, filter: “brightness(0.78)” },
animate: { x: 0, scale: 1.2, transition: { duration: 1.8 } },
};
画像をすこし拡大し、左(-80)から右(0)に移動させます。またホバーしたときに再度拡大し、明るさを0.78から1まで上げましょう。
scaleではなくscaleXとscaleYを使った理由は、ホバーをはずす際にFramer Motionが1.8秒のアニメーション時間を使わないようにするため。不要な機能に対するトリックのようなものです。
returnの一部も見てみましょう。
return (
<> { /** this is a placeholder **/
<div id=”gallery”>
<div className="item">
<motion.img
variants={zoom}
initial=”initial”
animate=”animate”
whileHover={hover}
src=”assets/pic4.jpg”
></motion.img>
<Detail title=”Araki Toshida” role=”photographer” />
</div>
... other "items"
...
画像と<Derail />ブロックをどちらも保持する「item」がありますね。
画像の親コンテナ(item)を使うことで、画像のスケーリングによるoverflowを防ぎましょう。
スタイリングはとてもシンプルです。
#gallery {
overflow: hidden;
position: absolute;
height: 100vh;
}
#gallery .item {
width: 25%;
height: 100%;
float: left;
overflow: hidden;
position: relative;
}
#gallery .item img {
width: 100%;
height: 100%;
object-fit: cover;
}
overflowはhiddenに設定し、画像を拡大してコンテナを覆います。
もっともシンプルなブロックが、この詳細情報です。基本的にCSSのみで対応できます。
function Detail({ title, role }) {
return (
<div className=”details”>
<h3>{title}</h3>
<p>{role}</p>
<span> > </span>
</div>
);
}
たとえばtitleとroleをパラメータとして受け取り、それらを内部でテキストとして使用するシンプルなコンポーネント関数を定義してみましょう。
<Detail title={“something”} role={“something else”} />
CSSはすこし長めです。
#gallery .item .details {
background: white;
width: 100%;
position: absolute;
bottom: -300px;
height: 300px;
transition: bottom 0.5s;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
padding: 20px;
}
#gallery .item:hover .details {
bottom: 0px;
}
.details h3 {
font-size: 40px;
font-family: “Bambi”;
}
.details span {
width: 80px;
height: 80px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: black;
color: white;
position: absolute;
bottom: 30px;
right: 30px;
transition: background 0.5s, color 0.5s;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
.details span:hover {
background: rgba(0,0,0,0);
border: 2px black solid;
color: black;
cursor: pointer;
}
基本的には以下の5つのパーツを定義しました。
今回はFramer Motionの使いかたをお伝えするために、シンプルなコンポーネントを定義し、値を渡し、variantなどを使ってアニメーションを実装しました。
JavaScriptのおかげで、このようなアニメーションのワークフローはCSSよりもパフォーマンスが高く、またスムーズにレンダリングできます。
最後に、モーションコーディングのヒントをお伝えします。
ぜひこの記事を参考に、Framer Motionを使ってみてください。
(執筆:Lorenzo Doremi 翻訳:中島あすか 編集:齊藤颯人)
jQuery不要で最短5秒!ScrollRevealでフェードインを簡単実装してみよう
Workship MAGAZINE
コーディング必要なし!LottieでWebアニメーションを作ってみよう
Workship MAGAZINE
簡単3ステップで視差効果スライダーを作ってみよう!【GSAP/CSS Grid/Flexbox】
Workship MAGAZINE