はじめに
こういうアニメーションが作りたい
See the Pen xxKPBzw by m_n_r (@m_n_r) on CodePen.
See the Pen NWKwJOL by m_n_r (@m_n_r) on CodePen.
環境
Sass(Sass 記法)
Compass
■ のうごき
白い画面で ■ が現れて、 ■ が消えて、文字が現れる
一文字につき、一つの ■ がある
一文字につき、一つの ■ をつくる
HTML
<div class="fade-in-word__vertical">
<span>W</span><span>E</span><span>L</span><span>C</span><span>O</span><span>M</span><span>E</span>
</div>
一文字につき、一つの ■ をつけるために span
で囲います
<span><span></span>W</span>
■ と文字を連動させるために、span
の中に ■ を入れる必要があります
今回は疑似要素で対応できるので、中の span
はいりません
<span>W</span>
文字を表示する SASS
.fade-in-word
font-size: 10px
&__vertical
font-size: 4em
line-height: 1.1em
この状態では文字がちょっと大きく表示されるだけです
アニメーション部分は mixin に書きます
mixin ってなに?
何度も使うスタイルをあらかじめ定義しておくことができます
@include
で呼び出して使用します
引数を渡すこともできるので、関数的な使い方ができちゃいます
一文字につき、一つの ■ をつくる SASS
@mixin fadeInWordY()
span
position: relative
display: inline-block
&:before
content: ''
display: block
height: 100%
width: 100%
background-color: #000
position: absolute
top: 0
left: 0
.fade-in-word
font-size: 10px
&__vertical
font-size: 4em
line-height: 1.1em
@include fadeInWordY()
こんな感じのができあがりました
■■■■■■■
一文字につき、一つの ■ を、文字サイズにあわせて覆うことができました
■ を交互に動かす
文字数を渡して関数化
@mixin fadeInWord-animationY($length)
文字数を渡して繰り返し利用できるように mixin にわけます
.fade-in-word
font-size: 10px
&__vertical
font-size: 4em
line-height: 1.1em
@include fadeInWordY(7)
@mixin fadeInWordY($length: 0)
span
position: relative
display: inline-block
&:before
content: ''
display: block
height: 100%
width: 100%
background-color: #000
position: absolute
top: 0
left: 0
@include fadeInWord-animationY($length)
文字数は @include fadeInWordY()
で直接指定します
■ を交互にフェードアウトさせる SASS
@mixin fadeInWord-animationY($length, $from: 1)
$delay: 0
@for $i from $from through $length
@if $i%2==0
span:nth-of-type(#{$i})
transform-origin: bottom
&:before
transform-origin: bottom
@else
span:nth-of-type(#{$i})
transform-origin: top
&:before
transform-origin: top
span:nth-of-type(#{$i})
&:before
animation: notScaleY 0.3s ease forwards
$delay: $delay + 0.1
@keyframes notScaleY
100%
transform: scaleY(0)
■ がこんな感じで動くようになりました
■■■■■■■
■ ■
W E L ■■■■
■
■ ■ ■ ■
W E L C O M E
■ ■ ■
待機中の ■ をみえないように
アニメーションが開始する直前(ロード直後)
■■■■■■■
が全部表示されてしまっています
最初は ■ を非表示にしておいて、フェードアウトし始める少し前に表示されるようにしましょう
@mixin fadeInWordY($firstLine: 0, $secondLine: 0)
span
position: relative
display: inline-block
transform: scaleY(0)
@mixin fadeInWord-animationY($length, $from: 1)
span:nth-of-type(#{$i})
animation: scaleY 0.36s ease (0.1s + $delay) forwards
&:before
animation: notScaleY 0.3s ease (0.45s + $delay) forwards
うーん・・・なんかちょっとちがう・・・
真骨頂「cubic-bezier」
アニメーションの変化量を細かく調整する
span:nth-of-type(#{$i})
animation: scaleY 0.36s cubic-bezier(0.84, 0.01, 0.78, 0.13) (0.1s + $delay) forwards
&:before
animation: notScaleY 0.3s cubic-bezier(0.11, 1.05, 0.32, 1.03) (0.45s + $delay) forwards
サンプル通りに動くアニメーションができました
設定するとしないで、まったく違う動きになっているように見えます
cubic-bezier ってなに?
の、説明のまえに
CSS animation では次の設定を行うことができます
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
この中で animation-timing-function
を指定する際に使用しています
animation - CSS: カスケーディングスタイルシート | MDN
cubic-bezier の使い方
アニメーションの変化量をカスタムできます
CSS3のtransition-timing-functionの値、cubic-bezier()に関して
次のような形で値を設定します
animation-timing-function: cubic-bezier(0.11, 1.05, 0.32, 1.03)
変化量を直感的に決められるサイト
細かい数字を自分で調整しなくても、便利なサイトがあります
今の数字は、ここでちょっとずつ調整しながら決めました
2 行でもできるように
1 行目の先頭文字の ■ は下から上に
2 行目の先頭文字の ■ は上から下に
変形がはじまる原点を変える
1 行ずつ mixin を適用する
要素が変形する際の原点は、次のプロパティで設定可能です
transform-origin - CSS: カスケーディングスタイルシート | MDN
先頭文字の transform-origin
を、引数で指定するのはどうでしょう
<div class="fade-in-word__vertical-oneline">
<span>W</span><span>E</span><span>L</span><span>C</span><span>O</span><span>M</span><span>E</span>
</div>
<br>
<div class="fade-in-word__vertical-twoline">
<span>P</span><span>A</span><span>G</span><span>E</span>
</div>
.fade-in-word
font-size: 10px
&__vertical
font-size: 4em
line-height: 1.1em
&-oneline
@include fadeInWordY(7, top)
&-twoline
@include fadeInWordY(7, bottom)
それぞれの要素を div
で囲っています
これでも構わないのですが、同じ要素内でないと都合が悪い場合もあります
今回はもともと構造が決まっていたうえで、アニメーションを追加する対応だったので
同じ要素内で 2 行が対応できるようにしました
1 行目と 2 行目を判定する
2 行目の文字数も引数で渡すようにします
2 行目の場合、先頭文字の transform-origin
に設定される方向を逆にしました
<div class="fade-in-word__vertical">
<span>W</span><span>E</span><span>L</span><span>C</span><span>O</span><span>M</span><span>E</span>
<br>
<span>P</span><span>A</span><span>G</span><span>E</span>
</div>
.fade-in-word
font-size: 10px
&__vertical
font-size: 4em
line-height: 1.1em
@include fadeInWordY(7, 4) // (1 行目の文字数, 2 行目の文字数)
@mixin fadeInWordY($firstLine: 0, $secondLine: 0)
span
position: relative
display: inline-block
transform: scaleY(0)
&:before
content: ''
display: block
height: 100%
width: 100%
background-color: #000
position: absolute
top: 0
left: 0
@if $firstLine != 0
@include fadeInWord-animationY($firstLine)
@if $secondLine != 0
@include fadeInWord-animationY($firstLine + $secondLine, $firstLine + 1, TRUE)
@mixin fadeInWord-animationY($length, $from: 1, $vector: FALSE)
$delay: 0
$status: 0
@if $vector==TRUE
$status: 2
@else
$status: 1
@for $i from $from through $length
@if $status%2==0
span:nth-of-type(#{$i})
transform-origin: bottom
&:before
transform-origin: bottom
@else
span:nth-of-type(#{$i})
transform-origin: top
&:before
transform-origin: top
$status: $status + 1
span:nth-of-type(#{$i})
animation: scaleY 0.36s cubic-bezier(0.84, 0.01, 0.78, 0.13) (0.1s + $delay) forwards
&:before
animation: notScaleY 0.3s cubic-bezier(0.11, 1.05, 0.32, 1.03) (0.45s + $delay) forwards
$delay: $delay + 0.1
追記(2019/9/18)
関数の書き方こっちの方がいいかもしれない
きれいな書き方ってむずかしい
@mixin fadeInWord-animationY($length, $from: 1, $vector: FALSE)
$delay: 0
$start: ''
$next: ''
span
animation: scaleY 0.36s cubic-bezier(0.84, 0.01, 0.78, 0.13) forwards
&:before
animation: notScaleY 0.3s cubic-bezier(0.11, 1.05, 0.32, 1.03) forwards
@if $vector==TRUE
$start: top
$next: bottom
@else
$start: bottom
$next: top
span:nth-of-type(odd)
transform-origin: $start
&:before
transform-origin: $start
span:nth-of-type(even)
transform-origin: $next
&:before
transform-origin: $next
@for $i from $from through $length
span:nth-of-type(#{$i})
animation-delay: 0.1s + $delay
&:before
animation-delay: 0.45s + $delay
$delay: $delay + 0.1
縦向き
変更点をあげる
@mixin fadeInWordX($firstLine: 0, $secondLine: 0)
writing-mode: vertical-rl
span
position: relative
display: inline-block
transform: scaleX(0)
&:before
content: ''
display: block
height: 100%
width: 100%
background-color: #000
position: absolute
top: 0
left: 0
@if $firstLine != 0
@include fadeInWord-animationX($firstLine)
@if $secondLine != 0
@include fadeInWord-animationX($firstLine + $secondLine, $firstLine + 1, TRUE)
writing-mode: vertical-rl
テキストのレイアウトを垂直方向にしました
transform: scaleX(0)
横向きに広がるように scaleX
に変えました
基本的に横と縦では scaleX
と scaleY
が逆になります
@mixin fadeInWord-animationX($length, $from: 1, $vector: FALSE)
$delay: 0
$status: 0
@if $vector==TRUE
$status: 2
@else
$status: 1
@for $i from $from through $length
@if $status%2==0
span:nth-of-type(#{$i})
transform-origin: left
&:before
transform-origin: left
@else
span:nth-of-type(#{$i})
transform-origin: right
&:before
transform-origin: right
$status: $status + 1
span:nth-of-type(#{$i})
animation: scaleX 0.35s cubic-bezier(0.84, 0.01, 0.78, 0.13) (0.1s + $delay) forwards
&:before
animation: notScaleX 0.3s cubic-bezier(0.11, 1.05, 0.32, 1.03) (0.45s + $delay) forwards
$delay: $delay + 0.1
transform-origin
縦と横が変わるので、上下と左右も変わります
-
animation-name: scaleX
とanimation-name: notScaleX
keyframes はこちら
@keyframes scaleX
100%
transform: scaleX(1)
@keyframes notScaleX
100%
transform: scaleX(0)
animation-duration: 0.35s
これは好みの問題かもしれませんが、同じ秒数だと印象が違ったのでほんの少し調整しました
おわりに
1 行のみ、または 2 行に対応しています
現在の書き方は複数行に対応していませんが、引数を増やせば拡張可能です