【JS・CSS】 ウェブでアニメーションする方法を徹底的に調べてみた

この記事は約21分で読めます。
サーバー等の運営維持費を得るため記事内に自動表示される広告が含まれています

イメージ

こんにちは、さち です。

先日、ウェブサイトでアニメーションをさせる方法について、調べる機会がありました。

その時に、CSStransition animation を使う方法も知ったのですが、これが結構複雑で使い方を理解するには多くの知識が必要でした。

今回は、私が学んだ内容を徹底的にまとめました。多くのサンプルも付けて分かりやすい解説を心がけたので、お役に立てれば幸いです。

スポンサーリンク

jQuery(JavaScript) でアニメーション

jQuery(JavaScript)の animate を使ってアニメーションさせます。JavaScript で CSS の値を変更させて動かします。

サンプルコード

<button type="button">クリックで移動</button>
<div></div>
div {
  position: relative;
  left: 0px;
  width: 75px;
  height: 75px;
  background-color: #F00;
}
$('button').click(function() {
  $('div').animate({'left':'200px'}, 2000, 'swing');
});
サンプル

構造の解説

$('div').animate(
  {'プロパティ名':'アニメーション終点の値'},
  アニメーションにかける時間,
  '変化の速度'
);

プロパティ名

アニメーションさせる CSS プロパティを指定。
width margin など数値を扱うものなら何でもOK。コンマで区切って複数指定可能。

{'left':'200px'} //1つだけ指定
{'left':'200px', 'width':'150px', 'height':'150px'} //複数指定

アニメーション終点の値

アニメーションの終点の値を指定。単位は、px 以外に em % でもOK。
相対的な変化を指定することも可能。

{'left':'200px'} //「200px」の位置に移動する(絶対移動)
{'left':'+=50px'} //現在位置から右に「50px」移動する(相対移動)
{'left':'-=30px'} //現在位置から左に「30px」移動する(相対移動)

アニメーションにかける時間

【初期値】 400[ミリ秒]

アニメーションにかける時間を指定。数値の単位は「ミリ秒」。
数値の代わりに、「slow =600ミリ秒」「fast =200ミリ秒」も利用可能。

animate({'left':'200px'}, 1000, 'swing') //1秒かけてアニメーション
animate({'left':'200px'}, 'slow', 'swing') //0.6秒かけてアニメーション

変化の速度

【初期値】 swing

アニメーションの変化の速度を指定。
swing linear の2種類から選択可能。

animate({'left':'200px'}, 500, 'swing'); //加速→減速
animate({'left':'200px'}, 500, 'linear'); //一定速度
サンプル

長所・短所

長所
  • 恐らく、コードの行数が一番少なく手間がかからない
  • jQuery がサポートしているブラウザすべてで動くため
    ブラウザ毎の実装の違いを気にする必要がない
短所
  • jQuery の導入が必要(大した手間ではないけれど)
  • CPUが非力だと動きがカクつく(特に、スマホで顕著)

 

transition(CSS)でアニメーション

CSS の transition を使ってアニメーションさせます。

アニメーション用に .move クラスを作り、そこに transition でアニメーションの制御を記述。.move クラスを <div> 要素に JavaScript で追加することでアニメーションを発動します。

サンプルコード

<button type="button">クリックで移動</button>
<div></div>
/* アニメーション前の状態 */
div {
  position: relative;
  left: 0px;
  width: 75px;
  height: 75px;
  background-color: #F00;
}

/* アニメーション後の状態 */
.move {
  left: 200px;
  transition-property: left;
  transition-duration: 2s;
  transition-timing-function: ease-in-out;
  transition-delay: 0s;
}
$('button').click(function() {
  $('div').addClass('move'); //divにクラス「move」を追加
});
サンプル

構造の解説

.move {
  プロパティ名: アニメーション終点の値;
  transition-property: アニメーションさせるプロパティ名;
  transition-duration: アニメーションにかける時間;
  transition-timing-function: 変化の速度;
  transition-delay: 開始を遅らせる時間;
}

transition-property(アニメーションさせるプロパティ名)

【初期値】 all

アニメーションさせるプロパティ名を指定。
width margin など数値を扱うものなら何でもOK。コンマで区切って複数指定可能。
all で全プロパティをアニメーション。

transition-property: left; /* 1つだけ指定 */
transition-property: left, width, height; /* 複数指定 */
transition-property: all; /* すべてのプロパティを指定*/

transition-duration(アニメーションにかける時間)

【初期値】 0s

アニメーションにかける時間を指定。
「ミリ秒 ms」または「秒 s」で指定(1秒=1000ミリ秒)。
Firefox では「0秒」でも単位省略不可。

transition-duration: 2s; /* 2秒かけてアニメーション */
transition-duration: 2500ms; /* 2.5秒かけてアニメーション */

transition-timing-function(変化の速度)

【初期値】 ease

アニメーションの変化の速度を指定。
ease ease-in ease-out ease-in-out linear step-start step-end の7種。
steps(ステップ数,startまたはend) でステップ数分だけ段階的に変化。
cubic-bezier で3次ベジェでの数値指定も可能(解説省略)。

transition-timing-function: ease; /* 加速→減速 */
transition-timing-function: ease-in; /* 加速 */
transition-timing-function: ease-out; /* 減速 */
transition-timing-function: ease-in-out; /* easeよりゆっくり加速→減速 */
transition-timing-function: linear; /* 一定速度 */
transition-timing-function: step-start; /* 即終点 */
transition-timing-function: step-end; /* 終点直前まで始点を維持 */
transition-timing-function: steps(5,start); /* 5段変化(始点で即変化) */
transition-timing-function: steps(5,end); /* 5段変化(始点を維持) */
サンプル

transition-delay(開始を遅らせる時間)

【初期値】 0s

アニメーションの開始を遅らせる時間を指定。
「ミリ秒 ms」または「秒 s」で指定(1秒=1000ミリ秒)。
Firefox では「0秒」でも単位省略不可。

transition-delay: 0s; /* すぐにアニメーション開始 */
transition-delay: 2500ms; /* 2.5秒後にアニメーション開始 */

transition(まとめて指定)

前述の各プロパティは transition でまとめて書くことも可能。
秒数は先に書いた方が transition-duration として認識されます。

.move {
  left: 200px;
  transition-property: left; /* アニメーションさせるプロパティ名 */
  transition-duration: 2s; /* アニメーションにかける時間 */
  transition-timing-function: ease-in-out; /* 変化の速度 */
  transition-delay: 0s; /* 開始を遅らせる時間 */
}

/* 「transition」でまとめて書くことも可能 */
.move {
  left: 200px;
  transition: left 2s ease-in-out 0s;
}

片側トランジション/両側トランジション

transition をどこに記述するかで、トランジションが「片側だけ」または「両側」に付くかが変わります。

アニメーション後の方に記述(片側トランジション)

/* アニメーション前の状態 */
div {
  position: relative;
  left: 0px;
  width: 75px;
  height: 75px;
  background-color: #F00;
}

/* アニメーション後の状態 */
.move {
  left: 200px;
  transition: left 2s ease-in-out 0s;
}
サンプル

アニメーション前の方に記述(両側トランジション)

/* アニメーション前の状態 */
div {
  position: relative;
  left: 0px;
  width: 75px;
  height: 75px;
  background-color: #F00;
  transition: left 2s ease-in-out 0s;
}

/* アニメーション後の状態 */
.move {
  left: 200px;
}
サンプル

ベンダープレフィックス

ブラウザに試験実装されているプロパティの名前の頭に付く -webkit- -moz- などがベンダープレフィックスです。

ブラウザのバージョンによってはベンダープレフィックスを付けないと、transition が機能しません。

各ブラウザのベンダープレフィックスは次のとおり。動かないブラウザを極力減らすなら全部書いておくのが無難です。

.move {
  -webkit-transition: left 2s ease-in-out 0s; /* Chrome25, Safari6, Android Browser4.3 以前用 */
  -moz-transition: left 2s ease-in-out 0s; /* Firefox15 以前用 */
  -o-transition: left 2s ease-in-out 0s; /* Opera12 以前用 */
  transition: left 2s ease-in-out 0s;
}

現在は、ベンダープレフィックスなしでも動くブラウザがほとんどです。iOS 6 以前にも対応したい場合は -webkit- を書きましょう。(参考: CSS3 Transitions - Can I use...

長所・短所

長所
  • ハードウェアアクセラレーション(GPU処理)が効くことがあるため
    jQuery(JavaScript) で動かすより動きがスムーズになる
  • :hover 等の擬似クラスに使うなら JavaScript は不要
短所
  • 旧バージョンブラウザも考慮すると記述が増えて面倒
  • jQuery より分かりにくい

animation(CSS)でアニメーション

CSS の animation を使ってアニメーションさせます。

アニメーション用に .move クラスを作り、そこに animation でアニメーションの制御を記述。.move クラスを <div> 要素に JavaScript で追加することでアニメーションを発動します。

サンプルコード

<button type="button">クリックで移動</button>
<div></div>
/* アニメーション前の状態 */
div {
  position: relative;
  width: 75px;
  height: 75px;
  background-color: #F00;
}

/* アニメーションの設定 */
.move {
  animation-name: anime;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: 0s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-play-state: running;
}

/* アニメーションの内容 */
@keyframes anime {
    0% { left:   0px; }
  100% { left: 200px; }
}
$('button').click(function() {
  $('div').addClass('move'); //divにクラス「move」を追加
});
サンプル

構造の解説

.move {
  animation-name: 適用する「アニメーション名」;
  animation-duration: アニメーションにかける時間;
  animation-timing-function: 変化の速度;
  animation-delay: 開始を遅らせる時間;
  animation-iteration-count: 繰り返し回数;
  animation-direction: 繰り返し時の逆再生の有無;
  animation-fill-mode: 開始前,終了後の状態;
  animation-play-state: 再生と一時停止の制御;
}

@keyframes アニメーション名 {
    0% { プロパティ名: アニメーション始点の値; }
  100% { プロパティ名: アニメーション終点の値; }
}

@keyframes(アニメーションの名前と内容の指定)

@keyframes の後に「アニメーションの名前」を記述。
{ } 内にアニメーションのタイミングと内容を指定。
タイミングはアニメーションの始点が 0%,終点が 100%
その瞬間の「プロパティ名」「値」でアニメーションの内容を指定。

@keyframes anime {
    0% { left:   0px; } /* 始点のアニメーションの内容 */
   30% { left:  50px; } /* 30%経過時のアニメーションの内容 */
  100% { left: 100px; } /* 終点のアニメーションの内容 */
}

/* from(0%), to(100%) と書くことも可能 */
@keyframes anime {
  from { left:   0px; } /* 始点のアニメーションの内容 */
  to   { left: 100px; } /* 終点のアニメーションの内容 */
}

animation-name(適用するアニメーションの名前)

適用する「アニメーションの名前」を指定。
「アニメーションの名前」は @keyframes の後に続く部分(※前項を参照)。

animation-name: anime; /* animeという名前のアニメーションを適用 */

animation-duration(アニメーションにかける時間)

【初期値】 0s

アニメーションにかける時間を指定。
「ミリ秒 ms」または「秒 s」で指定(1秒=1000ミリ秒)。
Firefox では「0秒」でも単位省略不可。

animation-duration: 2s; /* 2秒かけてアニメーション */
animation-duration: 2500ms; /* 2.5秒かけてアニメーション */

animation-timing-function(変化の速度)

【初期値】 ease

アニメーションの変化の速度を指定。
ease ease-in ease-out ease-in-out linear step-start step-end の7種。
steps(ステップ数,startまたはend) でステップ数分だけ段階的に変化。
cubic-bezier で3次ベジェでの数値指定も可能(解説省略)。

animation-timing-function: ease; /* 加速→減速 */
animation-timing-function: ease-in; /* 加速 */
animation-timing-function: ease-out; /* 減速 */
animation-timing-function: ease-in-out; /* easeよりゆっくり加速→減速 */
animation-timing-function: linear; /* 一定速度 */
animation-timing-function: step-start; /* 即終点 */
animation-timing-function: step-end; /* 終点直前まで始点を維持 */
animation-timing-function: steps(5,start); /* 5段変化(始点で即変化) */
animation-timing-function: steps(5,end); /* 5段変化(始点を維持) */
サンプル

animation-delay(開始を遅らせる時間)

【初期値】 0s

アニメーションの開始を遅らせる時間を指定。
「ミリ秒 ms」または「秒 s」で指定(1秒=1000ミリ秒)。
Firefox では「0秒」でも単位省略不可。

animation-delay: 0s; /* すぐにアニメーション開始 */
animation-delay: 2500ms; /* 2.5秒後にアニメーション開始 */

animation-iteration-count(繰り返し回数)

【初期値】 1[回]

アニメーションの繰り返し回数を指定。
小数も指定可能。infinite で無限に繰り返し。

animation-iteration-count: 2; /* 2回繰り返す */
animation-iteration-count: 0.5; /* 半分(50%)アニメーションする */
animation-iteration-count: infinite; /* ずっと繰り返す */

animation-direction(繰り返し時の逆再生の有無)

【初期値】 normal

繰り返し時にアニメーションを逆再生させるかを指定。
normal alternate reverse alternate-reverse の4種。
(旧バージョンのブラウザは reverse alternate-reverse が未対応の場合あり)

animation-direction: normal; /* 始点に戻って繰り返し */
animation-direction: alternate; /* 偶数回は逆再生 */
animation-direction: reverse; /* 毎回逆再生 */
animation-direction: alternate-reverse; /* 奇数回は逆再生 */
サンプル

animation-fill-mode(開始前,終了後の状態)

【初期値】 none

アニメーション開始前,終了後の状態を指定。
none forwards backwards both の4種。

animation-fill-mode: none; /* 開始前も終了後もアニメーション適用前の状態 */
animation-fill-mode: forwards; /* アニメーション終了後は終点を維持 */
animation-fill-mode: backwards; /* アニメーション開始前は始点を維持 */
animation-fill-mode: both; /* 開始前は始点、終了後は終点を維持 */
サンプル

animation-play-state(再生と一時停止の制御)

【初期値】 running

アニメーションの再生/一時停止を制御します。
running paused の2種。
擬似クラス や JavaScript で再生制御に用いるのが主(?)。
値を調べることで「再生中」かどうかの判別にも使用可能。

animation-play-state: running; /* 再生 */
animation-play-state: paused; /* 一時停止 */
サンプル

animation(まとめて指定)

前述の各プロパティは animation でまとめて書くことも可能。
ただし、animation-play-state (再生/一時停止の指定)は記述不可。
秒数は先に書いた方が animation-duration として認識されます。

.move {
  animation-name: anime; /* 適用するアニメーション名 */
  animation-duration: 2s; /* アニメーションにかける時間 */
  animation-timing-function: ease-in-out; /* 変化の速度 */
  animation-delay: 0s; /* 開始を遅らせる時間 */
  animation-iteration-count: 1; /* 繰り返し回数 */
  animation-direction: normal; /* 繰り返し時の逆再生の有無 */
  animation-fill-mode: forwards; /* 開始前,終了後の状態 */
}

/* 「animation」でまとめて書くことも可能 */
.move {
  animation: anime 2s ease-in-out 0s 1 normal forwards;
}

ベンダープレフィックス

ブラウザに試験実装されているプロパティの名前の頭に付く -webkit- -moz- などがベンダープレフィックスです。

各ブラウザのベンダープレフィックスは次のとおり。動かないブラウザを極力減らすなら全部書いておくのが無難です。

.move {
  -webkit-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Chrome, Safari, Android Browser 用 */
  -moz-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Firefox15 以前用 */
  -o-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Opera12 用*/
  animation: anime 2s ease-in-out 0s 1 normal forwards;
}

/* Chrome, Safari, Android Browser 用 */
@-webkit-keyframes anime {
    0% { left:   0px; }
  100% { left: 200px; }
}

/* Firefox15 以前用 */
@-moz-keyframes anime {
    0% { left:   0px; }
  100% { left: 200px; }
}

/* Opera12 用*/
@-o-keyframes anime {
    0% { left:   0px; }
  100% { left: 200px; }
}

@keyframes anime {
    0% { left:   0px; }
  100% { left: 200px; }
}

現在は、ベンダープレフィックスなしで動くブラウザがほとんどです。iOS 8 以前にも対応したい場合は -webkit- を書きましょう。(参考: CSS3 Animation - Can I use...

長所・短所

長所
  • アニメーションとデザインのCSSを切り離して書ける
  • transition より複雑なアニメーションを作れる
  • :hover 等の擬似クラスや常に動くものに使うなら JavaScript は不要
短所
  • プロパティが多く記述が長くなりやすい(ややこしい)
  • ハードウェアアクセラレーション(GPU処理)が効かない
  • -webkit- のベンダープレフィックス必須(2014年9月現在)

transition, animation が動かない時の確認点

transition animation を使ったアニメーションを作った時に、記述に間違いが無さそうなのに動かないことが何度かありました。

原因を探るのに苦労したので、同じことで困っている人のためにまとめておきます。

「0秒」でも単位は省略できない

transition: left 2s ease 0; /* 動かない */
transition: left 2s ease 0s; /* 動く */

margin padding などは数値が 0 のとき単位を省略可能。そのせいで transition animation の秒数指定でも「0秒」なら単位を省略できると思いがちです。

他のブラウザでは単位を省略しても動きます。しかし、「Firefox」は動きません。

「0秒」であっても必ず単位を付けましょう。

アニメーション前の値は指定が必要

/* 動かない */
div {
  position: relative;
  width: 75px;
  height: 75px;
  background-color: #F00;
}
.move {
  left: 200px;
  transition: left 2s ease-in-out 0s;
}

/* 動く */
div {
  position: relative;
  left: 0px;
  width: 75px;
  height: 75px;
  background-color: #F00;
}
.move {
  left: 200px;
  transition: left 2s ease-in-out 0s;
}

初期値で自動的に値が決まるものは書かなくてもいいだろう。そう思いがちです。

上の例なら、<div> 要素の left の値は未記入でも 0px なのは当然。0px から transition が実行されそうに思えます。

しかし、大半のブラウザでは動きません。(一部の旧バージョンブラウザでは動きます)

アニメーションに使う値は、必ず「前」と「後」の両方を記述しましょう。

「display」の「none→block」は動かない

/* 動かない */
div {
  display: none;
  opacity: 0;
}
.fade {
  display: block;
  opacity: 1;
  transition: opacity 2s ease-in-out 0s;
}

/* 動く */
div {
  height: 0;
  overflow: hidden;
  opacity: 0;
}
.fade {
  height: auto;
  opacity: 1;
  transition: opacity 2s ease-in-out 0s;
}

アニメーションの前は display: none; で要素を隠しておき、アニメーション開始時に display: block; で表示させるという手法は非常に使いたくなります。

しかし、この方法を使うと transition が効きません。

height0auto に変化させれば代用に近いことはできます。ただし、height0 であっても、margin padding border が空白として残るので前後で書き換えが必要。また、あふれた中身が見えないよう overflow: hidden; も必須です。

display を使った 表示/非表示 の操作に、CSSアニメーションが対応してくれれば一番楽なんですけどね。

コメント

タイトルとURLをコピーしました