抹桥的博客
Language
Home
Archive
About
GitHub
Language
主题色
250
1590 文字
8 分
CSS3で実現するキャラクターの競走アニメーション

最近、会社のモバイルプロジェクトで、ランニングトラックを走る人のアニメーションがありました。モバイルデバイスでより良いパフォーマンスを発揮するために、すべてCSS3でアニメーションを作成することにしました。 初めての試みだったので、多くの問題に遭遇しました。ここに記録しておきます。

完成イメージは次のとおりです。 All

分析#

完成イメージを見て、まず分析してみましょう。アニメーションは以下の4つの部分に分けられます。

  • 走る人
  • 動く道
  • 左側の道路標識
  • 収益の看板

走る人#

走る人は簡単に解決できます。ランニングの分解画像を使用し、 person background-positionをフレームごとに変更するだけで済みます。本当に簡単ですね。

.person {
    width: 62px;
    height: 110px;
    background: url(../imgs/plan/person1.png) -7px 0 no-repeat;
    background-size: auto 110px;
    animation: run .5s infinite;			// 各ブラウザのプレフィックス、特に-webkit-を追加することに注意してください。ここでは省略します。
    position: absolute;
    top: 40%;
    left: 110*.84px;
}
@keyframes run {
    0% {
        background-position: -7px 0
    }
    25% {
        background-position: -79px 0
    }
    50% {
        background-position: -150px 0
    }
    75% {
        background-position: -216px 0
    }
    100% {
        background-position: -283px 0
    }
}

しかし、走る人はこのようになってしまいました。 person-wrong 見るに堪えません。原因を分析したところ、keyframesがデフォルトでトランジションを持っているためでした。つまり、background-positionが-7から-283まで線形にグラデーションしていたのです。これはもちろん私が望む結果ではありません。これはアニメーションタイミング関数の問題だと考え、animation-timing-functionの値を調べました。

linear: 線形トランジション。ベジェ曲線(0.0, 0.0, 1.0, 1.0)と同等。 ease: 滑らかなトランジション。ベジェ曲線(0.25, 0.1, 0.25, 1.0)と同等。 ease-in: ゆっくり始まり、速くなる。ベジェ曲線(0.42, 0, 1.0, 1.0)と同等。 ease-out: 速く始まり、ゆっくりになる。ベジェ曲線(0, 0, 0.58, 1.0)と同等。 ease-in-out: ゆっくり始まり、速くなり、またゆっくりになる。ベジェ曲線(0.42, 0, 0.58, 1.0)と同等。 step-start: steps(1, start)と同等。 step-end: steps(1, end)と同等。 steps([, [ start | end ] ]?): 2つの引数を受け取るステップ関数。最初の引数は正の整数でなければならず、関数のステップ数を指定します。2番目の引数はstartまたはendのいずれかの値を取り、各ステップの値が変化する時点を指定します。2番目の引数はオプションで、デフォルト値はendです。 cubic-bezier(, , , ): 特定のベジェ曲線タイプ。4つの数値は[0, 1]の範囲内である必要があります。

stepというプロパティこそが私たちが求めていたものです。これにより、ある状態から別の状態へ直接ジャンプさせることができ、トランジションは発生しません。上記の.personにこのプロパティを追加するだけで済みます。

animation-timing-function: step-start;

person-run これで走る人の問題は解決しました。

#

道については、最初は良い方法が思いつきませんでした。当初は、大きなセクションを直接切り取り、2枚の画像を作成して、それらを交互に表示することを考えていました。しかし、これでは画像が非常に大きくなり、ネットワークリソースを消費するだけでなく、非常に非効率な方法だと感じました。ランニングトラックを見て分析した結果、良い方法を思いつきました。 runway ランニングトラックの最小構成要素を切り取り、縦方向に繰り返し配置し、background-positionを画像の高さの半分ずつ移動させるだけで済みます。 runway-run これで道の問題も解決しました。

左側の道路標識#

これは非常に簡単で、絶対位置を設定し、top値を変更するだけで済みます。 注意すべき点は、最後の標識が中央に到達した後に停止することです。これには、このプロパティを追加するだけで対応できます。

animation-fill-mode: forwards;

animation-fill-modeプロパティは、アニメーションが再生される前または後に、そのアニメーション効果が表示されるかどうかを規定します。 none: デフォルトの動作を変更しません。 forwards: アニメーションが完了した後、最後のプロパティ値(最後のキーフレームで定義されたもの)を保持します。 backwards: animation-delayで指定された期間中、アニメーションが表示される前に、開始プロパティ値(最初のキーフレームで定義されたもの)を適用します。 both: 前方と後方の両方のフィルモードが適用されます。

収益の看板#

左側の道路標識と同様に、非常に簡単です。ただ現れて消えるだけです。

組み合わせ#

アニメーションの4つの部分を解決した後、残りはそれらを組み合わせることです。 process 上の図は、最初の道路標識が画面に現れてから消えるまでのプロセスフローチャートです。他の2つの道路標識のプロセスは、アニメーションを対応する時間だけ遅延させるだけで済みます。 この間に、もう一つ問題がありました。それは、走る人と道を特定の場所で停止させることです。 これはCSS3では実現できないようだったので、次善の策としてJavaScriptで制御することにしました。webkit-animation-play-state: pausedwebkit-animation-play-state: runningというプロパティを設定することで、停止後に再び動かすことができます。 最後に、アニメーションが完了した後にポップアップを表示する必要があります。これはanimationEndイベントを検出することで実現します。以下にその実装方法を示します。

/* From Modernizr */
function whichAnimationEvent(){
    var t;
    var el = document.createElement('fakeelement');
    var animations = {
      'animation':'animationend',
      'OAnimation':'oAnimationEnd',
      'MozAnimation':'animationend',
      'WebkitAnimation':'webkitAnimationEnd'
    }

    for(t in animations){
        if( el.style[t] !== undefined ){
            return animations[t];
        }
    }
}

/* Listen for a transition! */
var transitionEvent = whichAnimationEvent();
whichAnimationEvent && e.addEventListener(whichAnimationEvent, function() {
	//doSomething
});

/*
	The "whichTransitionEvent" can be swapped for "animation" instead of "transition" texts, as can the usage :)
*/

効果#

これが最終的な完成効果です。 こちらをクリックしてアニメーションを見る

この記事は 2015年5月21日 に公開され、2015年5月21日 に最終更新されました。3791 日が経過しており、内容が古くなっている可能性があります。

CSS3で実現するキャラクターの競走アニメーション
https://blog.kisnows.com/ja-JP/2015/05/21/income-plan-animation/
作者
Kisnows
公開日
2015-05-21
ライセンス
CC BY-NC-ND 4.0