Graviness Blog

算数・数学・科学・電脳・雑記・アホの順の密度で記事が構成されます。
<< November 2018 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >> ブログランキング・にほんブログ村へ
 
RECOMMEND
ビッグバン宇宙論 (上)
ビッグバン宇宙論 (上) (JUGEMレビュー »)
サイモン・シン, 青木 薫
RECENT COMMENT
  • 豊臣秀吉と曾呂利新左衛門から学ぶ数列の和
    優乃 (07/12)
  • 【誰か解いて】漸化式 a_(n+1) = f(n) * a_n ^ g(n) + h(n) の一般項
    優乃 (02/18)
  • 【誰か解いて】漸化式 a_(n+1) = f(n) * a_n ^ g(n) + h(n) の一般項
    S.S.+ (02/16)
  • 豊臣秀吉と曾呂利新左衛門から学ぶ数列の和
    坂井昭 (03/19)
  • d/dx(x↑↑n): 高さが定数のテトレーションの微分 - 数学的帰納法を用いる方法
    (09/30)
  • 全ての三角形は二等辺三角形
    優乃 (09/28)
  • 全ての三角形は二等辺三角形
    亀レス (09/28)
  • 全ての三角形は二等辺三角形
    優乃 (09/24)
  • 全ての三角形は二等辺三角形
    亀レス (09/23)
  • 【未解決】新しい演算子を創る
    $_ (09/10)
RECENT TRACKBACK
MOBILE
qrcode
PROFILE
無料ブログ作成サービス JUGEM
 
【数学・DHTML】 イージング [Easing] (1)
はるか昔のことになりますが,コマ割を変えるEdging という考えで加減速移動を行う方法を説明しました.
作成当時から^^;,この方法(sin関数使用)では加速(減速)の程度に限界があることを感じていました.
加速(減速)は実現できるものの,なんか物足りない,ということです.

sin関数なんて軟弱な関数でオフセット量を決めるからいけない,もっと放物線とか高次関数とか急激に変化する関数を使うべよ.
と思ったのが昨日の話です.

ということでn次関数を使用する方法を紹介します.
先ず,アニメーションの雛形.
var x0 = 100; // 始点のX座標
var x1 = 500; // 終点のX座標

function move(currentCount, endCount) {
    if (currentCount <= endCount) {
        var c = currentCount++ / endCount;

        e.style.left = ??? + "px";

        setTimeout("move(" + currentCount + ", " + endCount + ");", 10);
    }
}
c の範囲は[0, 1]で,時間みたいなもんだと思いねぇ.

ちなみに等速移動のときは以下のようになる.
var x0 = 100; // 始点のX座標
var x1 = 500; // 終点のX座標

function move(currentCount, endCount) {
    if (currentCount <= endCount) {
        var c = currentCount++ / endCount;

        e.style.left = (x0 + (x1 - x0) * c) + "px";

        setTimeout("move(" + currentCount + ", " + endCount + ");", 10);
    }
}

実際の例はこちら(等速)


問題は???がどういった式になるかだ.

さて,ここからは ??? を求めることになるわけだが,まず ???x0, x1, c を含むことを分かっていただきたい.(分からない方は,上記,等速移動の例Edging を参考にしてくれぃ)

??? を関数 f で置き換えると x0(始点), x1(終点)は定数なので,fc の関数となる.f = f(c)
始点が x0 で終点が x1 であるので,f(c) は以下を満たす.
f(0) = x0
f(1) = x1
プログラムで書いておく(以下).
var x0 = 100; // 始点のX座標
var x1 = 500; // 終点のX座標

function move(currentCount, endCount) {
    if (currentCount <= endCount) {
        var c = currentCount++ / endCount;

        e.style.left = f(c) + "px";

        setTimeout("move(" + currentCount + ", " + endCount + ");", 10);
    }
}

// f(c) は f(0) = x0, f(1) = x1 を満たす.
function f(c) {
    return ???;
}

さて,f(c) にn次関数を使用する,と最初に書いた.

結論に近い式を書きたいところだが,いきなりは難しいので,n次関数ではなく,2次関数で f(c) がどうなるかを考えて頂きたい.

0 <= c <= 1で,x0 から出発して,2次関数で増加させて,x1 に到達するような関数は
    f(c) = ? * c ^ 2 + x0
に似たような式になるはずだ.

実は0 <= c <= 1 であれば,これを3次にしようが,4次にしようが,10次にしようが f(c) の軌跡は大体似たようなものになる(相似)

以上をふまえて以下のような式が思いつく.
f(c) = k0 * c ^ n + k1

    k0, k1 は未知の定数
    n が後々の「加減速の程度(イージング値)」を決める値になる
未知数は2つ(k0, k1).条件式も2つあるのでこれは解ける.
f(0) = x0より
  f(0) = x0 = k1

f(1) = x1より
  f(1) = x1 = k0 + k1

∴ k0 = x1 - x0, k1 = x0

よって

f(c) = (x1 - x0) * c ^ n + x0 ,,
これはn = 1のとき,等速移動になることを覚えておこう.

さて,これで完了だ.
nが大きいときに加速も大きくなることは直感的に分かる(2乗よりも4乗,4乗よりも10乗).
迷わないようにプログラムにして実際の例もリンクしておく.
var x0 = 100; // 始点のX座標
var x1 = 500; // 終点のX座標
var n = 6; // 加速の程度(指数,1以上)

function move(currentCount, endCount) {
    if (currentCount <= endCount) {
        var c = currentCount++ / endCount;

        e.style.left = f(c) + "px";

        setTimeout("move(" + currentCount + ", " + endCount + ");", 10);
    }
}

function f(c) {
    return x0 + (x1 - x0) * Math.pow(c, n);
}
実際の例はこちら(n=6

これをグラフにするとこのようになる(加速)

前回(sin関数)との大きな違いは「加速の程度を決める変数」に上限がないことだ.n は1以上の任意の値をとることができる.

さぁ,加速移動はできた!
これを減速移動にも適用だ!・・・んっ?どうすりゃいいの?

大きくなればなるほど,加速が顕著になることを思って,何も考えずに n にマイナスの値をつっこむと痛い目を見る.また,0 < n < 1で代入しても同じく痛い目をみる.

要はこのようなグラフになるようにすればいいわけだ.実はそんなに難しいことではない(だろう)が,眠たくなったので完成形は次回にまわす.

関連:
イージングの考え方
【数学・DHTML】 イージング [Easing] (1)
【数学・DHTML】 イージング [Easing] (2)
【数学】 イージングロジックメモ
【数学・DHTML】 イージング [Easing] (3)
【DHTML】 加速・減速を考慮したアニメーションプログラム
【数学・DHTML】 イージング [Easing] (4)
【数学・DHTML】 イージング [Easing] (5)
コメント
コメントする









 
トラックバック
この記事のトラックバックURL
http://blog.graviness.com/trackback/41785
 

(C) 2018 ブログ JUGEM Some Rights Reserved.