1 ポイント 投稿者 GN⁺ 2024-03-09 | 1件のコメント | WhatsAppで共有

指数平滑化を使ったアニメーションの小技

  • アニメーションに関する作業を始めて以来、ほとんどいつも使ってきたシンプルなアニメーション手法がある。
  • この手法は、カメラの回転や移動、ターン制ゲーム内でのキャラクター移動、UI要素の移動、オーディオライブラリにおける音量変化の平滑化など、さまざまな場面で使われる。
  • この手法は新しいものではなく、すでに聞いたことがあったり使ったことがあったりするかもしれないが、ここではいくつかの例と数学的な原理を説明する。

トグルボタン

  • UIコンポーネントを作る際、たとえばトグルボタンを作ると仮定する。
  • トグルボタンのスイッチ位置は状態に応じて計算され、オンなら max_x、オフなら min_x に設定される。
  • この方式はうまく機能するが、アニメーションがないとやや生気がないように見える。
  • アニメーションは見た目の良さを加えるだけでなく、何が起きているのかをユーザーが理解する助けにもなる。
  • トグルインジケーターを即座に新しい位置へ動かす代わりに、なめらかに移動するよう変更する。
  • ここでアニメーションを更新する必要があり、これは一定速度で移動しているように見えるという欠点がある。
  • そこでイージング関数を追加し、たとえば 3t^2-2t^3sqrt(t) のような関数を使える。
  • こうしたイージング関数の違いは、アニメーションをゆっくり再生したときによくわかる。
  • これで、スイッチ位置を更新する代わりにアニメーション状態を追跡しなければならなくなる。
  • sqrt を使う場合は、アニメーションの方向に応じて別のイージング関数を明示的に使う必要がある。
  • どれがいちばん良く見えるかは好みの問題だが、sqrt がもっとも良く見える。スイッチが非常に速く動き始め、目的地に近づくにつれてうまく減速するからだ。
  • このバージョンの欠点は、もっとも単純なケースでもかなりの管理が必要であり、ユーザーがアニメーションの途中でクリックすると突然跳ねるような不連続性が生じることだ。

カメラ移動

  • マップとカメラが周囲をスクロールしたり移動したりする状況を考える。
  • ここでもアニメーションを追加するのが望ましい。
  • 定速で補間するコードを示す。
  • アニメーション完了後に発生する揺れは、target.x - position.x が正と負の間で交互に変化するためだ。
  • sign(delta) の代わりに、デルタをクランプする関数が必要になる。
  • この方法は、単純なことに対してかなり複雑だ。
  • アニメーション速度がアニメーション完了より速いと不自然に見える。
  • アニメーションが有効な間はユーザー入力を無視することもできるが、それはユーザーにとってかなり苛立たしい体験になる。
  • 完璧な解決策は、もちろん指数平滑化だ。
  • コードはトグルボタンの例と比べてほとんど変わらない。

内部の仕組み

  • 1 - exp(- speed * dt) が何なのか、そしてどのように動作するのかを説明する。
  • まずは単純なバージョンから始め、現在の position と移動先の新しい位置 target の差に比例して速度を決めることで、移動速度を速くする。
  • この方法は、現在位置と目標位置以外にいかなる状態も保持する必要がなく、target が突然変わっても自動的に調整される。
  • しかし小さな問題がある。speed * dt が 1 より大きいと、位置が目標を通り過ぎてしまう。
  • この問題を解決するために、値を 1 にクランプできる。
  • speed * dt が大きすぎる理由は、speed の値が大きすぎるか、dt が大きすぎるためだ。
  • アニメーションでは、dt を適用したときにすべてが完全に動作してくれるのが理想だ。

微分方程式 (ああ、いやだ)

  • 問題を解決するための2段階のアプローチを示す。
  • position += (target - position) * speed * dt が小さな dt では機能するが、大きな dt では破綻するのは、微分方程式の数値解法でよくある典型的な問題だ。
  • この方程式が何を解いているのかを見ていく。
  • position += (target - position) * (1 - exp(- speed * dt)) が、あらゆる dt に対して正しい式であることを説明する。

速度の選び方

  • アニメーションは通常、継続時間の観点で考える。
  • 指数の式を使うと、アニメーションは技術的には無限の時間をかけて完了する。
  • speed パラメータの意味は、1 / speedpositiontargete = 2.71828... 倍だけ近づくのにかかる時間だということだ。

指数平滑化

  • 「指数平滑化」を検索すると、まったく無関係に見えるWikiの記事が見つかるかもしれないが、実際にはこの投稿で議論しているものと非常によく似た式が載っている。
  • dt が常に同じで、target が毎反復ごとに変化すると仮定すると、反復番号で値に添字を付けて position[i] = (target[i] - position[i - 1]) * factor のようなものを計算する。

最後の段落の見出し

  • この投稿のアイデアは数か月前から持っていて、ようやく完成できてうれしい。
  • 開発ログを見て、読んでくれてありがとう。

GN⁺の意見

  • この記事は、アニメーションをなめらかで自然に見せるために使われる指数平滑化手法について説明している。この手法は、ユーザー体験を向上させ、インターフェースの直感性を高めるのに役立つ。
  • 指数平滑化は、物理的な動きをシミュレートするうえでも有用であり、たとえばゲーム開発でキャラクターの動きやカメラ移動をより自然に見せるために使える。
  • この手法は特に、ユーザーインターフェースの要素が状態変化を経験するとき、その変化を視覚的に表現するのに非常に効果的だ。たとえば、スライダーやスイッチの動きをよりなめらかに表現できる。
  • 批判的な観点から見ると、指数平滑化はアニメーションの速度や継続時間を正確に制御しにくい場合がある。これは、デザイナーが特定のアニメーション効果を精密に調整したいときに制約となりうる。
  • 類似の機能を提供する他のアニメーションライブラリやフレームワークとしては、GreenSock Animation Platform(GSAP) や anime.js などがあり、これらはさまざまなイージング関数とともに、より細かなアニメーション制御を提供する。
  • 指数平滑化手法を導入する際には、アニメーションの自然さと制御の精密さのあいだでバランスを取る必要がある。この手法を選ぶことで得られる利点はユーザー体験の向上であり、欠点はアニメーションの厳密なタイミング調整が難しい可能性がある点だ。

1件のコメント

 
GN⁺ 2024-03-09
Hacker Newsの意見
  • 1つ目のコメント要約:

    • この手法は単純なイージング曲線や smoothstep() 関数ではなく、さまざまな入力を一貫して扱うステートレスな方法であることを強調している。
    • CSS トランジションを使った経験があれば、この技術が解決する問題を理解できる。
    • 指数平滑化には、目的地に近づいていくが決して到達しないという問題がある。
    • 慣性スクロールに似た方法を使うとき、(疑似的な)摩擦項を追加するのが有用だったと述べている。
  • 2つ目のコメント要約:

    • ゲーム開発者として、ほとんどの UI の場面では、あらかじめ持続時間が設定されたイージングトゥイーンを好む。
    • しかし、始点や終点が明確でない連続的で予測不可能な動きを滑らかにするときには、この技術が非常に役立つ。
    • 指数的線形補間(exponential lerp)は有用だが広く知られておらず、一部のゲームでは精度の低い線形補間を使ってアニメーションの問題を抱えている。
    • そのためこの記事に感謝しており、この種の特定知識にはアクセスしにくいことが多いと述べている。
  • 3つ目のコメント要約:

    • 著者がトグルスイッチについて平方根(sqrt)のほうが三次関数(cubic)より良いと主張している点に異論を示している。
    • 実際のトグルスイッチの動作を考えると、三次関数のほうが適していると主張している。
    • アニメーションがユーザー体験を向上させられることをよく示した記事だと評価している。
  • 4つ目のコメント要約:

    • オンラインでのインタラクションに楽しさを加える、シンプルな非線形のトリックに感心している。
    • 色の知覚で重要な役割を果たし、人は加速度を常に理解できるわけではない点に触れている。
  • 5つ目のコメント要約:

    • この記事を気に入っており、ほぼ 10 年前に lazy-easy という名前で同じ技術を書いたことがあると述べている。
    • 状態管理なしで滑らかなアニメーションが欲しいときに、今でもこの技術を使っているという。
  • 6つ目のコメント要約:

    • イージングに関する記事は、どの世代でも新たに再発見しなければならないもののように見えると述べている。
    • 90年代後半のユーゴ・ナカムラの実験的なウェブサイトが、イージングを自在に使って有機的な感触を与えた最初期の例のひとつだったと振り返っている。
  • 7つ目のコメント要約:

    • タッチやクリックを押し続けている間はゆっくり動き、離すと残りが素早くスナップするトグルのアイデアを示している。
    • UX の観点でこれが何を意味するか確信はないが、設定が適用または保存されるタイミングを示せるかもしれないと考えている。
  • 8つ目のコメント要約:

    • この技術はスイッチだけでなく、さまざまな用途に有用だと評価している。
    • Flickity に関連するデモに触れつつ、この技術には本番投入に必要なさまざまな最適化が含まれていないと指摘している。
    • コメント欄で、人々が記事をきちんと読んでいないか、重要な内容を見落としていると批判している。
  • 9つ目のコメント要約:

    • この記事を好意的に評価しつつ、デモは Chrome ではうまく動くが Firefox ではページが固まる問題を経験したと述べている。
  • 10個目のコメント要約:

    • 小さなアニメーションには多くの物語が込められており、感情的デザインの最高の形だと評価している。