インターフェイスでの自然なアニメーション





\ begin {tikzpicture} \ def \ t {0} \ def \ r {3.1415} \ begin {axis} [width = 12cm、height = 7cm、ticks = none、xmin = -0.5、xmax = 3.8、axis y line =左、軸x line = bottom、xlabel = $ t $、ylabel = $ x $、すべての軸x label / .style = {at = {(current axis.south east)}、anchor = south}、すべての軸yラベル/.style={at={(current axis.north west)}、アンカー= west}、enlargelimits = true、マークサイズ= 1] \ addplot [smooth、blue、domain = \ t:\ r、samples = 80] {1-cos(deg(x * 3))}; \ addplot [mark = *]座標{(\ t、0)}; \ addplot [mark = *]座標{(\ r、2)}; \ end {axis} \ end {tikzpicture}










0. KDPV







インターフェイスのアニメーションは、その状態を視覚的に変化させます。 たとえば、送信に失敗した場合、長いフォームは誤って入力されたフィールドにスクロールします。 または、を押して拡大した写真は、周囲の要素を押し広げます。







アニメーションがなければ、突然の突然の変化を認識することはより困難です。 ただし、アニメーションはユーザーの邪魔にならないように短くて目立たないものにする必要があります。







アニメーションは、世界中のオブジェクトの通常の動きを繰り返すと自然に見えます。 カットの下で、物理法則に基づいてアニメーションを作成する方法を説明します。 デモページで完成した結果を確認します (マウスが移動すると、1つのブロックが他のブロックに続きます)。







物理学を覚えて



オブジェクトの移動は、時間tにわたるx座標の変化によって記述されます。 関数xt )を「目で」選択しようとすると、滑らかで自然な動きを実現するのに多くの時間を費やします。 何を選択しますか? 双曲線? 放物線? どこに移動しますか? 回す方法は?







動きの例については、世界のオブジェクトに目を向けることが最善です。 彼らの運動の数学的法則は物理学によって決定されます。 テーブルの上にあるバーを押します。 一定の距離を移動し、摩擦の作用により減速します。 適切な近似では、乾式滑り摩擦の力は一定であり、依存性xt )は放物線であることがわかります。 このスローダウンは、最初の時点でアニメーションオブジェクトが既に動いていた場合に使用できます。











\ begin {tikzpicture} \ def \ t {0} \ def \ r {3.4} \ begin {axis} [width = 10cm、height = 7cm、ticks = none、xmin = -0、xmax = 3.8、axis y line =左、軸x line = bottom、xlabel = $ t $、ylabel = $ x $、すべての軸x label / .style = {at = {(current axis.south east)}、anchor = south}、すべての軸yラベル/.style={at={(current axis.north west)}、anchor = west}、enlargelimits = true、マークサイズ= 1] \ addplot [smooth、blue、domain = \ t:\ r、samples = 80] {-(x- \ r)^ 2}ノード[pos = 0.75、黒、アンカー=南東、内側sep = 2pt] {$ x = A + Bt + Ct ^ 2 $}; \ addplot [破線、ドメイン= \ r-0.7:\ r、サンプル= 2] {0}; \ addplot [mark = *]座標{(\ t、-\ r * \ r)}; \ addplot [マーク= *、緑!50!黒]座標{(\ r、0)}ノード[ピン= -90:{\ scriptsize {\ text {soft stop :)}}}] {}; \ end {axis} \ end {tikzpicture}










1.放物線の乾燥摩擦による抑制







粘性摩擦の力は、体の速度に比例します。 この場合、ボディは無限に長い間指数関数的に停止点に移動します。 移動時間を制限するために出展者が歪んでいる場合、そのようなアニメーションは不自然に見えます。 妥当な時間で停止するのが難しいため、粘性摩擦のシミュレーション自体が目標でない場合にのみ、粘性摩擦モデルを使用しないでください。











\ begin {tikzpicture} \ def \ t {0} \ def \ r {3.8} \ begin {axis} [width = 10cm、height = 7cm、ticks = none、xmin = -0、xmax = 3.8、axis y line =左、軸x line = bottom、xlabel = $ t $、ylabel = $ x $、すべての軸x label / .style = {at = {(current axis.south east)}、anchor = south}、すべての軸yラベル/.style={at={(current axis.north west)}、anchor = west}、enlargelimits = true、マークサイズ= 1] \ addplot [smooth、blue、domain = \ t:\ r、samples = 80] {1-exp(-x * 1.0)}ノード[pos = 0.45、黒、アンカー=南東、内側sep = 2pt] {$ x = A-Be ^ {-\ alpha t} $}; \ addplot [破線、ドメイン= \ t:\ r、サンプル= 2] {1}; \ addplot [mark = *]座標{(\ t、0)}; \ addplot [赤!80!黒]座標{(3.4,1)}ノード[ピン= -90:{\ scriptsize {\ text {停止しない:(}}}] {}; \ end {axis} \ end { tikzpicture}










2.粘性媒体で指数関数的にブレーキをかけます







平衡位置から外れた振り子(またはバネの重り)はスムーズに速度を増し、平衡位置を通過し、徐々に減速します。 次に、反対方向に動きが繰り返され、無限に続きます(摩擦がない場合)。 このような動きのグラフは正弦波です。 周期的な繰り返しは私たちにとって特に興味深いものではありませんが、極点間の振り子の動きは滑らかで自然です。











\ begin {tikzpicture} \ def \ t {0} \ def \ r {3.1415} \ begin {axis} [幅= 10cm、高さ= 7cm、目盛り=なし、マークサイズ= 1、xmin = -0.5、xmax = 3.6 、軸y線=左、軸x線=下、xlabel = $ t $、ylabel = $ x $、すべての軸xラベル/ .style = {at = {(current axis.south east)}、anchor = south} 、すべての軸yラベル/ .style = {at = {(current axis.north west)}、anchor = west}、enlargelimits = true] \ addplot [smooth、blue、domain = \ t:\ r、samples = 80] {1-cos(deg(x))}ノード[pos = 0.52、黒、アンカー=南東、内側sep = 2pt] {$ x = AB \ cos \ omega t $}; \ addplot [破線、ドメイン= \ t:\ t + 0.6、サンプル= 2] {1-cos(deg(\ t))}; \ addplot [破線、ドメイン= \ r-0.6:\ r、サンプル= 2] {1-cos(deg(\ r))}; \ addplot [マーク= *、緑!50!黒]座標{(\ t、0)}ノード[ピン= 90:{\ scriptsize {\ text {soft start :)}}}] {}; \ addplot [mark = *、green!50!black]座標{(\ r、2)} node [pin = -90:{\ scriptsize {\ text {\ quad soft stop :)}}}] {}; \ end {axis} \ end {tikzpicture}










3.極点間の正弦曲線に沿った振り子の動き







JSライブラリとCSSには、特殊効果を作成するためのイージング関数があります。 特別な場合には、ほとんどすべてのブランクを注意して使用する必要があります。 正弦波のみが多かれ少なかれ普遍的です。







第一に、正弦波軌道は身体をある静止位置から別の静止位置に移動します。 第二に、そのような動きの期間は期間の半分に等しい。 動きは時間的に制限されています。 期間は、外部の状況や初期条件に依存しません。 それはシステム自体の特性のみに依存し、剛性と慣性の比によって決定されます。







通常、200ミリ秒の正弦波でアニメーションの継続時間を選択します。 この期間は、人の反応時間の数倍です。 アニメーションははっきり見えますが、イライラする時間はありません。







初期条件、移動時間、停止点に応じて正弦波軌道を実行する方法を学びましょう。







2点を通して正弦波を描く方法



体を最初と最後の時点で休ませます。 次に、ポイントt 1およびt 2でのグラフの接線水平であり、グラフ自体は正弦波の半サイクルです。











\ begin {tikzpicture} \ def \ t {0} \ def \ r {3.1415} \ begin {axis} [ticks =なし、xmin = -1、xmax = 4.5、軸y行=左、軸x行=下、 xlabel = $ t $、ylabel = $ x $、すべての軸x label / .style = {at = {(current axis.south east)}、anchor = south}、すべての軸y label / .style = {at = { (現在のaxis.north west)}、アンカー= west}、enlargelimits = true] \ addplot [smooth、blue、domain = \ t:\ r、samples = 80] {1-cos(deg(x))}; \ addplot [破線、ドメイン= \ t:\ t + 1、サンプル= 2] {1-cos(deg(\ t))}; \ addplot [破線、ドメイン= \ r-1:\ r、サンプル= 2] {1-cos(deg(\ r))}; \ addplot [マーク= *、マークサイズ= 1]座標{(\ t、0)}ノード[ピン= 95:{$(t_1、x_1)$}] {}; \ addplot [マーク= *、マークサイズ= 1]座標{(\ r、2)}ノード[ピン= -85:{$(t_2、x_2)$}] {}; \ end {axis} \ end {tikzpicture}










4. 2つの静止位置間の移動のスケジュール







正弦波の半サイクルを表す方程式は簡単に選択できます。











x(t)= x_1 + {x_2-x_1 \ over 2} \ left [1-\ cos \ left(\ pi {t-t_1 \ over t_2-t_1} \ right)\ right]。










1つのアニメーションの終了後、この式を使用して別のアニメーションを再び開始できます。 しかし、古いアニメーションが終了する前に新しいアニメーションが開始されるとしたらどうでしょうか? スムーズな動きを保証するために、現在のアニメーションを停止し(青い線)、ゼロ以外の初期速度で新しいアニメーションを開始します(赤い線):











\ begin {tikzpicture} \ def \ tgnt {0.7} \ def \ t {0} \ def \ r {3.1415} \ def \ tb {1} \ def \ rb {\ r + \ tb} \ def \ dx {1.27} \ begin {axis} [ticks = none、xmin = -1、xmax = 4.9、axis y line = left、axis x line = bottom、xlabel = $ t $、ylabel = $ x $、すべての軸x label / .style = {at = {(current axis.south east)}、anchor = south}、すべての軸yラベル/ .style = {at = {(current axis.north west)}、anchor = west}、enlargelimits = true、markサイズ= 1] \ addplot [smooth、blue、domain = \ t:\ tb、samples = 80] {-cos(deg(x))+ 1}; \ addplot [スムーズ、点線、青、ドメイン= \ tb:\ r、サンプル= 10] {-cos(deg(x))+ 1}; \ addplot [青、破線、ドメイン= \ t:\ t + \ tgnt、サンプル= 2] {-cos(deg(\ t))+ 1}; \ addplot [smooth、thick、red、domain = \ tb:\ rb、samples = 80] {-1.5 * cos(deg(1 + 0.69 *(x- \ tb)))+ \ dx}; \ addplot [破線、赤、ドメイン= \ tb- \ tgnt:\ tb + \ tgnt、サンプル= 2] {-1.5 * cos(deg(\ tb))+ \ dx + sin(deg(\ tb))*( x- \ tb)}; \ addplot [破線、赤、ドメイン= \ rb- \ tgnt:\ rb、サンプル= 2] {1.5+ \ dx}; \ addplot [mark = *]座標{(\ t、0)}; \ addplot [mark = *]座標{(\ tb、1-cos(deg(\ tb)))} node [pin = -85:{$(t_1、x_1)$}] {}; \ addplot [mark = *]座標{(\ r、2)}; \ addplot [マーク= *]座標{(\ rb、1.5 + \ dx)}ノード[ピン= -85:{$(t_2、x_2)$}] {}; \ end {axis} \ end {tikzpicture}










5.初期速度がゼロ以外のモーションのスケジュール







数学的な計算がなければ、赤い線に対応する式を書くことはできません。 この計算をしましょう。







考えられるすべての正弦波のファミリーは、方程式











f(t)= A \ cos \ omega(t-t_2)+ B \ sin \ omega(t-t_2)+ C










4つの未知のパラメーターABCおよび \オメガ> 0 。 すぐに2番目の用語を削除するために、時間レポートの先頭をポイントt 2に移動しました。 確かに、デリバティブ f '(t_2)= B \オメガ t 2での接線水平であるため、ゼロでなければなりません。 これは、 B = 0の場合に可能です。







以来 f(t_2)= x_2 その後、置換 t = t_2 (1)では、 f(t_2)= A + C 。 ここからCを除外します:











f(t)= x_2 + A \左[\ cos \ omega(t-t_2)-1 \右]。










スピードを見つけるために差別化する













f '(t)=-A \、\ omega \ sin \ omega(t-t_2)。










最初の瞬間の位置x 1と速度vがわかっています。











\ begin {cases} x_1 \!\!\!\!\!& = x_2 + A \ left [\ cos \ omega(t_1-t_2)-1 \ right]、\\ v \!\!\ !! \ !\!& =-A \、\ omega \ sin \ omega(t_1-t_2)。 \ end {cases}










この連立方程式から、 A\オメガ 。 新しい変数を導入する時が来ました k = \オメガ(t_2-t_1) の代わりに \オメガ 。 その意味は、開始点と終了点での正弦波の位相差です。 たとえば、図のグラフの場合 4 k = \ pi なぜなら (t_1、t_2) サイン波の半サイクルに適合します。 図 5 k< \ pi なぜなら t_2-t_1 期間の半分未満。







置換と小さな変換の後、システムに到達します











\ begin {cases} x_2-x_1& = A \ left(1- \ cos k \ right)、\\ v(t_2-t_1)\!\!\ !!!!& = A \、k \ sin k。 \ end {cases}










最初の方程式の項を2番目で除算します。











{x_2-x_1 \ over v(t_2-t_1)} = {1- \ cos k \ over k \ sin k} \ quad \ Rightarrow \ quad {1- \ cos k \ over \ sin k} = \ alpha k、 \ quad \ text {where} \ \ alpha = {x_2-x_1 \ over v(t_2-t_1)}。










パラメータ \アルファ 右側は事前に知られています。 動きの必要な性質を決定します。 もし \ alpha \ gg1 、初期速度が小さい場合、ボディは最初に加速する必要があります。 もし \ alpha \ ll1 、初期速度が速い場合、体は遅くなります。







左側の三角関数は、半角正接に縮小されます。 その結果、 kの非線形方程式があります。











\テキスト{tg} \、{k \ over2} = \ alpha k。










チャートで彼の決定を分析できます。 いくつかのパラメーター値の左右の部分のグラフを描いてみましょう \アルファ











\ begin {tikzpicture} \ small \ def \ aa {1.5} \ def \ ab {0.3} \ def \ ac {-0.5} \ begin {axis} [凡例pos =南東、マークサイズ= 1、サンプル= 2 yをドメイン= -8に制限する:8、幅= 12cm、高さ= 250pt、xmin = -10.5、xmax = 10.5、ytick = {-6、-3、...、6}、xtick = {-9.4247、- 3.1416、...、10}、xticklabels = {$-{3 \ pi} $、$-{\ pi} $、$ {\ pi} $、$ {3 \ pi} $}、軸x線=中心、軸y line = center、xlabel = $ k $] \ addplot [blue!70!black、domain = -9.4247:9.4247、semithick、samples = 802] {tan(deg(x / 2))}; \ addplot [red] {\ aa * x}; \ addplot [緑!70!黒、ドメイン= -9.4247:9.4247] {\ ab * x}; \ addplot [オリーブ、ドメイン= -9.4247:9.4247] {\ ac * x}; \ addplot [マーク= *]座標{(2.65,3.97)}ノード[アンカー=西] {$ A $}; \ addplot [マーク= *]座標{(8.69,2.61)}ノード[アンカー=西] {$ B $}; \ addplot [マーク= *]座標{(4.06、-2.03)}ノード[アンカー=西] {$ C $}; \凡例{$ \テキスト{tg} \、k / 2 $、$ \ aa \、k $、$ \ ab \、k $、$ \ ac \、k $} \ end {axis} \ end {tikzpicture}










6.式(2)のグラフィカルなソリューション







結果のソリューションについて説明します。







  1. ポイントAを検討します このソリューションは次の場合に存在します \アルファ> 1/2 図5に示すものに対応します。 \ begin {tikzpicture} \ def \ t {1} \ def \ r {3.1415} \ begin {axis} [幅= 1.9cm、高さ= 2cm、軸を非表示、目盛り=なし、xmin = \ t、xmax = \ r 、マークサイズ= 0.3] \ addplot [スムーズ、青、ドメイン= \ t:\ r、サンプル= 80] {-cos(deg(x))}; \ addplot [mark = *]座標{(\ t、-cos(deg(x)))}; \ addplot [mark = *]座標{(\ r、-cos(deg(x)))}; \ end {axis} \ end {tikzpicture} 。 予想通り k< \ pi 。 ゼロ速度の限界で \ alpha \ to \ infty 、赤い線は縦座標軸と一致し、ポイントAは無限大への接線に沿って進みます。 この制限で k \から\ pi 。 これまでのところ、すべてが順調に進んでいます。







  2. C\ alpha< 0 。 これは、時間の最初の瞬間に身体が前方に移動したときに起こりますが、後方に移動する必要があります。 いま \ pi< k< 2 \ pi 。 動きは、半周期よりも大きく、周期よりも短い正弦波の断片によって記述されます。

    \ begin {tikzpicture} \ def \ t {-1.7} \ def \ r {3.1415} \ begin {axis} [width = 2.2cm、height = 2cm、軸を非表示、目盛り= none、xmin = \ t、xmax = \ r、マークサイズ= 0.3] \ addplot [スムーズ、青、ドメイン= \ t:\ r、サンプル= 80] {cos(deg(x))}; \ addplot [mark = *]座標{(\ t、cos(deg(x)))}; \ addplot [mark = *]座標{(\ r、cos(deg(x)))}; \ end {axis} \ end {tikzpicture} 。 身体は減速し、停止し、後退し、目的の場所で停止します。







  3. グラフは、 0< \ alpha< 1/2 ポイントBは範囲内にあります 2 \ pi< k< 3 \ pi 。 身体は、振動の全周期よりも多く正弦波に沿って通過します。 \ begin {tikzpicture} \ def \ t {-1.6} \ def \ r {2 * 3.1415} \ begin {axis} [幅= 2.5cm、高さ= 2cm、軸を非表示、目盛り=なし、xmin = \ t、xmax = \ r、マークサイズ= 0.3] \ addplot [スムーズ、青、ドメイン= \ t:\ r、サンプル= 80] {cos(deg(x))}; \ addplot [mark = *]座標{(\ t、cos(deg(x)))}; \ addplot [mark = *]座標{(\ r、cos(deg(x)))}; \ end {axis} \ end {tikzpicture} 。 この奇妙な決定の理由は、停止点が特性距離vt 2 - t 1 )に比べて近すぎるためです。 したがって、停止と復帰を追加せずに正弦波を実行することはできません。













量子力学について
長方形のポテンシャル井戸内の粒子のエネルギーレベルに関する量子力学の問題を解くと、(2)と同様の方程式が生じます。 そこで、たとえば正弦波と指数をステッチする必要があります。 キンクがないという条件は、無限の数の根を持つ同様の方程式を与えます。







近似解



正弦波を実行するという数学的な問題を解決しましたが、これから人生は楽になりませんでした。 まず、正弦波のパラメーターを決定するには、非線形方程式を解く必要があります(2)。 こんにちは反復メソッド! 第二に、方程式には無限の解があり、必要な解が常に存在するとは限りません。







これらの問題は、アニメーションの継続時間を正確に200ミリ秒記録したという事実から生じました。 ただし、アニメーションが180ミリ秒続く場合、何も悪いことは起こりません。 または250ミリ秒です。 特定の場所で停止することがより重要であり、計算を簡素化するためにアニメーションの正確な継続時間を犠牲にします。







アニメーションの継続時間の要件を弱めて、このようなトリックを行います。 近似解があると仮定します k ' 非線形方程式(2)。 これは、異なるパラメーターを持つ方程式の正確な解です











\ alpha '= {1 \ over k'} \、\ text {tg} {k '\ over 2}、










別のアニメーション終了時間に対応します。











t_2 '= t_1 + {x_2-x_1 \ over v \ alpha'}。










軌道Aの未知のパラメーターと \オメガ 初等 k ' そして \ alpha '







私たちの目的に適した方程式(2)の近似を選択しました。











{1 \ over 2 \ alpha} \およそ1- \左({k \ over \ pi} \右)^ 2。










青い実線は正確な式(2)に対応し、赤い点線はその近似に対応します。











\ begin {tikzpicture} \ small \ begin {axis} [凡例pos =南東、yをドメインに制限= -8:8、幅= 12cm、xmin = -7.3、xmax = 7.3、ytick = {-6、-3 、...、6}、xtick = {-6.2832、-3.1416、...、10}、xticklabels = {$-{2 \ pi} $、$-{\ pi} $、$ 0 $、$ {\ pi} $、$ {2 \ pi} $}、軸x line = center、軸y line = center、xlabel = $ k $、ylabel = $ \ alpha $] \ addplot [スムーズ、サンプル= 580、青!70 !黒、ドメイン= -7:7] {tan(deg(x / 2))/ x}; \ addplot [スムーズ、サンプル= 580、赤、破線、ドメイン= -7:7] {0.5 /(1-(x / pi)^ 2)}; \凡例{$(1 / k)\、\テキスト{tg} \、k / 2 $、$ 0.5 / \!\左[1-({k / \ pi})^ 2 \右] $} \ end {軸} \ end {tikzpicture}










7.正確な関係(2)とその近似の比較







そしてまたの場合 0< \ alpha< 1/2 取ることをお勧めします \ alpha ' わずかに1/2以上にし、アニメーション時間を短縮して、跳ね返ったり戻ったりしないようにします。







申込み



コードと球状の使用例は、デモページにあります 。 マウスを動かして、黒いブロックがオレンジ色に追従する様子を確認します。







説明されているスキームは、最終製品に適用されます。 ソースの同期スクロールと数学テキストのmarkdown-およびlatex-エディターでのプレビュー用に開発しました。







markdown-it js parserのデモページでアイデアと初期実装を見つけました。 彼らのバージョンでは、アニメーションが破れ、速度が低下していることが判明しました。 これにはいくつかの理由があります。







  1. 線形関数はアニメーションに使用され$(...).stop(true).animate({scrollTop: ...}, 100, 'linear')



    $(...).stop(true).animate({scrollTop: ...}, 100, 'linear')



    。 スムーズなスケジュールの代わりに、破線が取得されます。
  2. jQuery().stop().animate()



    アニメーションjQuery().stop().animate()



    アニメーションjQuery().stop().animate()



    requestAnimationFrame()



    比べて遅くなります。
  3. パフォーマンスのonscroll



    を回避するために、50ミリ秒を超える頻度でonscroll



    イベントがonscroll



    ます。 私のバージョンでは、このような問題はありません。 連続するonscroll



    イベントは、ブレークポイントの位置を調整し、アニメーションを遅くしません。


製品にとって重要な高品質のアニメーションを実現するために、物理方程式に基づいた計算方法をrequestAnimationFrame()



、ブラウザベースの特別なrequestAnimationFrame()



メソッドを使用して実装しました。 このメソッドは、スクロールの移動に適しています:PageUp / PageDownキー、移動するスクロールバー、マウスホイール、タッチパッド、タッチスクリーン。











ソース投稿と写真
上記のエディターでこの投稿を入力しました。 私はソースを広めました。おそらく誰かがチャートのテックスコードを使用するでしょう。








All Articles