ヌルヌルっとスムーズスクロールの巻
smorgasbord は、F5キーを乗っ取って、独自の関数を呼ぶことで動的にレスを追加しています。せっかくなので、キーボードを活用したいところ。ということで、スペースキーが押下されたときは一番上に表示されているレスの次までスクロールする仕様にしました。同じように、右カーソルキーでも次のレスまでスクロール、左カーソルキーで逆に前のレスまでスクロールすることにしました。
ここで気づいたのは、普通に下カーソルキーでスクロールした場合、ズズッとスムーズスクロールされるのですが、単にscrollTo()を呼ぶだけだと、バチッとスクロールされてしまうので、どこからどこまでスクロールされたのかが視覚的に分かりづらい、ということ。せっかくなので、iPhone みたいにヌルヌルっと加速するスクロールをしてみたい。
が。どっから手をつけていいかわからない。あてもなく「加速度 スクロール」でググってみる。すると「等加速度運動」というキーワードを発見。なんだか一度高校で習った気がしないでもないが、文系なので全く覚えていない(致命的)。本棚から物理の参考書を探し出すと、さっそく公式を発見。
位置の公式: x = x0 + v0t + 1/2at2
うーん、この単元は高一の一番始めだったかもしれない。
とにかく、今回の用途では、現在のスクロール位置 (window.pageYOffset) から指定の場所までヌルヌルとスクロールさせたい。初速度は当然ゼロ。中点に来たところで、最高速度に達する。スクロールする距離に関わらず、一定の時間でスクロールさせないとユーザビリティに支障をきたすので、まずは適切な加速度を求めてあげなければならない。ここから先は、どうにかして中学生の数学の知識を必死に掘り返すしかない。とりあえず、上の公式を加速度 a についての方程式に式変形すると、
1/2at2 = x - x0 - v0t
a = 2(x - x0 - v0t) / t2
となる。初期位置 x0 と 初速度 v0 を無視すれば
a = 2x / t2
となる。位置 x に中点、時間 t に 中点に到達するまでの時間を代入してあげれば、加速度 a が求まる。あとは、最初の公式でその加速度を使い、スクロールする分割数を t として、ループを回してインクリメントしていけば位置が求まる。中点まで来たら、終点位置から (1/2)at2 を引いて、t をデクリメントしていきブレーキをかける。とりあえずコードを。
function smoothScrollTo(y) { var y1 = window.pageYOffset; var y2 = y if (y2 < 0) y2 = 0; if ((y2 + window.innerHeight) > document.body.offsetHeight) y2 = document.body.offsetHeight - window.innerHeight; var delta = y2 - y1; var steps = 16; var a = (delta / 2) * 2 / Math.pow(steps / 2, 2); var ha = a / 2; for (var x = 0; x < steps / 2; ++x) { window.scrollTo(0, y1 + (ha * Math.pow(x, 2))); } for (var x = steps / 2 - 1; x >= 0; --x) { window.scrollTo(0, y2 - (ha * Math.pow(x, 2))); } window.scrollTo(0, y2); }
ふぅ。なんとか実装できたみたい。PageDown, PageUp, Home, End なんかにもこれを適用してあげるとヌルヌルになっていい感じだ。同じようなことをする Firefox の拡張機能があったような気がしないでもないけど。