Last active
March 16, 2018 13:48
-
-
Save Caldis/cca942e448ddb8a04a2004ebaf2208cd to your computer and use it in GitHub Desktop.
Capture and smooth the scrolling for target dom
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const view = document.querySelector("#page>div") | |
class scroll { | |
constructor({ target, interpulator, precision }) { | |
// values | |
this.target = target // 目标 | |
this.precision = precision // 精确度 | |
this.interpulator = interpulator // 插值器 | |
this.timer = null // 计时器引用 | |
this.looping = false // 是否正在循环 | |
this.scrollCurrL1 = { x: 0, y: 0 } // 当前滚动距离 | |
this.scrollPoolL1 = { x: 0, y: 0 } // 累计滚动距离 | |
this.scrollCurrL2 = { x: 0, y: 0 } // 当前滚动距离 | |
this.scrollPoolL2 = { x: 0, y: 0 } // 累计滚动距离 | |
this.scrollDelta = { x: 0, y: 0 } // 滚动方向(保存上一次滚动的数值) | |
// Bind class function | |
this.tach = this.tach.bind(this) | |
this.detach = this.detach.bind(this) | |
this.startLoop = this.startLoop.bind(this) | |
this.looper = this.looper.bind(this) | |
this.stopLoop = this.stopLoop.bind(this) | |
this.capture = this.capture.bind(this) | |
this.post = this.post.bind(this) | |
} | |
// 钩子 | |
tach() { | |
this.target.addEventListener('wheel', this.capture, false) | |
} | |
detach() { | |
this.target.removeEventListener('wheel', this.capture, false) | |
} | |
// 处理循环 | |
startLoop({ force }={}) { | |
if (force || !this.looping) this.timer = window.requestAnimationFrame(this.looper) | |
this.looping = true | |
} | |
looper() { | |
// 获取插值结果 | |
const pulse = { | |
x: this.interpulator({ curr: this.scrollCurrL2.x, dest: this.scrollPoolL2.x }), | |
y: this.interpulator({ curr: this.scrollCurrL2.y, dest: this.scrollPoolL2.y }) | |
} | |
// 更新当前滚动位置 | |
this.scrollCurrL2.x += pulse.x | |
this.scrollCurrL2.y += pulse.y | |
// 更新滚动结果 | |
this.post(this.scrollCurrL2) | |
// 根据处理结果选择是否需要迭代循环 | |
Math.abs(this.scrollPoolL2.x-this.scrollCurrL2.x)>this.precision || | |
Math.abs(this.scrollPoolL2.y-this.scrollCurrL2.y)>this.precision ? | |
this.startLoop({ force: true }): | |
this.stopLoop() | |
} | |
stopLoop() { | |
this.looping && window.cancelAnimationFrame(this.timer) | |
this.looping = false | |
} | |
// 截取器 | |
capture(e) { | |
const { deltaX, deltaY } = e | |
// 归一化处理 | |
const x = normalize.max(deltaX, 100) | |
const y = normalize.max(deltaY, 100) | |
// 更新目标值 | |
if ((this.scrollPoolL2.x-this.scrollCurrL2.x)*x>=0) { | |
this.scrollPoolL2.x += x | |
} else { | |
this.scrollPoolL2.x = this.scrollCurrL2.x+x | |
} | |
if ((this.scrollPoolL2.y-this.scrollCurrL2.y)*y>=0) { | |
this.scrollPoolL2.y += y | |
} else { | |
this.scrollPoolL2.y = this.scrollCurrL2.y+y | |
} | |
// 更新Delta值 | |
this.scrollDelta.x = x | |
this.scrollDelta.y = y | |
// 启动循环 | |
this.startLoop() | |
} | |
// 发送器 | |
post({ x, y }) { | |
this.target.style.transform = `translate(${x}px, ${y}px)` | |
} | |
} | |
// 插值器 | |
const Interpulator = { | |
lerp: ({ damping }) => ({ curr, dest }) => (dest-curr)*damping | |
} | |
// 归一化 | |
const normalize = { | |
max: (val, limit) => Math.max(Math.abs(val), limit) * Math.sign(val), | |
min: (val, limit) => Math.min(Math.abs(val), limit) * Math.sign(val), | |
} | |
// 运行 | |
const lerp = Interpulator.lerp({ damping: 0.1 }) | |
const scroller = new scroll({ target: view, interpulator: lerp, precision: 0.1 }) | |
scroller.tach() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment