モジュールはこんな感じ:
control.js
'use strict';
import K from 'kefir';
import T from 'tween.js';
let d = global.document;
export let animationFrame = K.fromBinder((emitter) => {
let step = (timestamp) => {
global.requestAnimationFrame(step);
T.update(timestamp);
emitter.emit(timestamp);
};
global.requestAnimationFrame(step);
});
export let mousewheel = K.fromEvent(global, 'wheel');
export let wheelDeltaY = mousewheel.map((ev) => ev.deltaY);
export let scrollTop = wheelDeltaY.map((delta) => d.body.scrollTop + delta);
export let noop = () => true;
export let preventDefault = (ev) => {
ev.preventDefault();
return false;
};
export let applySmoothScroll = () => {
let throttledWheelDeltaY = wheelDeltaY.throttle(300);
animationFrame.onValue(noop);
mousewheel.onValue(preventDefault);
throttledWheelDeltaY.onValue((delta) => {
let t = new T.Tween({ scrollTop: d.body.scrollTop })
.to({ scrollTop: d.body.scrollTop + (delta * 0.6) }, 300)
.easing(T.Easing.Linear.None)
.onUpdate(function () { global.scroll(0, this.scrollTop); });
t.start();
});
};
スムーススクロールを実行するには次のようなコードを実行する:
import control from './control'
control.applySmoothScroll();
そもそもスムーススクロールの実装の考え方がこれで良いのか分からないけど、FRP で書くと、一つの事だけをやるモジュールを簡単に組み合わせられて、再利用性が向上するなーと思った。
まだまだ、サクサク書ける感じじゃないけど、書いていてとても楽しい。