JavaScript イージング easing
スムーズスクロールにイージング処理をつけたかったので調べた。
ease outとかease inとか。
読み込むファイルが増えるのは面倒なのでライブラリは使用しない。位置の移動や戻す処理を入れるならライブラリを使ったほうがよさそうだけど。
コード
// 1 イージングの関数を用意する。詳しくは下部「イージングについて」のリンク先参照 function easeOut(t, d){ return 1 - Math.pow(1 - (t / d), 5); } // 2 タイマーが重複しない処理を入れる(これはかなりテキトウ) if(timer){ clearInterval(timer) } var timer // 3 setIntervalなど定期処理でイージング関数のtに経過時間を代入する // bが初期値、cが変化量 function smoothScroll(ele, b, c){ var start = Date.now() , total = 1400 // ミリ秒 , delay = 16 // FPS 16で60FPS, 24で30FPSになる。負荷が無ければ , d = 1 timer = window.setInterval(function() { var t = (Date.now() - start) / total , result = easeOut(t, d) , y = b + result * c ele.scrollTop = y if (t >= d) { clearInterval(timer) } }, 16) } smoothScroll(document.documentElement, pageYOffset, 511) // smoothScroll(document.body, body.scrollTop, 511) // Webkit, Quirks-Mode
コードの説明
total timeはミリ秒で設定する。このコードだとスクロール開始から終了まで1.4秒かかる。
引数にele
を指定しているが、ウィンドウのスクロール量を変えるなら24行目をwindow.scrollTo(0, y)
で良い。
ページトップにスムーズスクロールするなら、下記のように設定すればよい。
smoothScroll(document.documentElement, pageYOffset, -pageYOffset)
イージングについて
- イージングの方法は Understanding Easing に分かりやすく説明されている
- イージングの関数は Tim Groleau's Easing Function Generator でいろいろ作れるので試すとよい。ボールをクリックしてそれから画面の適当な位置をクリックするとその関数通り動く。
- イージングのイメージ図は Tweener Documentation and Language Reference を参照
すこし日本語でも説明
イージング関数で使われる言葉
- b
- beginning value
- 初期値
- c
- change in value
- 変化値
- t
- time
- 現在時間
- d
- duretion
- 総時間
していること
- イージング関数で割合を得て、2. それと変化量をかけ、3. 初期値と足すだけ
総時間は要するに100分率だと考えればよい。
easeOut(10, 100) // 0.4 easeOut(20, 100) // 0.67 easeOut(30, 100) // 0.83 //--------------- easeOut(80, 100) // 0.99968 easeOut(90, 100) // 0.99999 easeOut(100, 100) // 1
最初のpageYOffset(b)が100, 最終的に位置したい場所(c)が1000pxだとすると
1000 * 時間の割合 + 100 でその時に位置すべき値を得ている。
時間が10%の時点で移動は40%、つまり 1000 * 0.4 + 100 = 600
時間が20%の時点で移動は67%、つまり 1000 * 0.67 + 100 = 770
時間が100%の時点で移動は100%、つまり 1000 * 1 + 100 = 1100
(下の説明のほうが分かりやすいかもしれない。)
別のイージング方法
イージングの関数がしていることを、配列で代用することもできる。
割合を配列に代入し、100で割って百分率にする。それを最終的に得たい変化量とかけるだけ。
例 1000px移動する
var percents = [0.1, 0.2, 0.3, 0.5, 0.7, 1, 1.5, 2, 2.5, 3, 4, 5, 7, 10, 15, 20, 30, 40, 50, 60, 70, 80, 83, 85, 90, 92, 93, 94, 95, 96, 97, 98, 98.5, 99, 99.3, 99.5, 99.7, 99.8, 99.9, 100] var b = pageYOffset var c = 2000 for(var i = 0, count = 0; i < percents.length; i++){ setTimeout(function(){ var easing = percents[count++] / 100 scrollTo(0, c * easing + b) }, i * 30) }