拖拽滑块中Linear interpolation(lerp)功能异常问题求助
线性插值(Lerp)实现滑块缓动时的回弹问题及解决
我最近在学习**线性插值(lerp)**以及如何用它实现缓动效果。目前滑块的缓动部分可以正常工作,但无法拖动到第3张幻灯片之后,滑块会像受惯性影响一样回弹至第1张幻灯片。
原代码
HTML
<main class='container'> <div class='slider'> <div class='slider__slide'>1</div> <div class='slider__slide'>2</div> <div class='slider__slide'>3</div> <div class='slider__slide'>4</div> <div class='slider__slide'>5</div> <div class='slider__slide'>6</div> <div class='slider__slide'>7</div> <div class='slider__slide'>8</div> <div class='slider__slide'>9</div> </div> </main>
CSS
* { margin: 0; padding: 0; box-sizing: border-box; } html,body { width: 100%; height: 100%; font-size: 100%; } body { display: grid; place-items: center; } .container { width: 90vw; height: 35vh; overflow-x: auto; scrollbar-width: none; cursor: grab; } .container::-webkit-scrollbar { display: none; } .slider { height: 100%; display: flex; gap: 0.25rem; } .slider__slide { min-width: 30vw; font: 900 1rem helvetica,sans-serif; background-color: rgb(65, 61, 70); color: white; display: grid; place-items: center; } .slider.active { cursor: grabbing; }
JavaScript
const slider = document.querySelector('.slider'); let active; let startX = 0; let endX = 0; let initLeft; function start(e) { active = true; slider.classList.add('active'); startX = e.pageX - slider.offsetLeft; initLeft = slider.scrollLeft; } function end() { active = false; slider.classList.remove('active'); } function move(e) { if (!active) return; e.preventDefault(); endX = e.pageX - slider.offsetLeft; } const lerp = (start,end,t) => start * (1-t) + end * t; function update() { startX = lerp(startX,endX,0.05); const dist = endX - startX; slider.scrollLeft = initLeft - dist; requestAnimationFrame(update); } window.addEventListener('load',update,false); slider.addEventListener('pointerdown',start,false); slider.addEventListener('pointermove',move,false); window.addEventListener('pointerup',end,false);
如果移除包含lerp的这行代码:
startX = lerp(startX,endX,0.05);
滑块就能正常拖动,但会失去缓动效果。我搞不清问题出在哪,希望能得到指点,任何反馈都感激不尽。
问题解决(更新)
最终我解决了这个问题,修正后的JavaScript代码如下:
const container = document.querySelector('.container'); const slider = document.querySelector('.slider'); let startX,endX; let startLeft,endLeft; let raf; const lerp = (start,end,t) => start * (1-t) + end * t; function update() { startLeft = lerp(startLeft,endLeft,0.03); const dist = (endX - startX) * 0.05; container.scrollLeft = startLeft - dist; raf = requestAnimationFrame(update); if (startLeft.toFixed(1) === endLeft.toFixed(1)) cancelAnimationFrame(raf); } function move(e) { endX = e.layerX endLeft = container.scrollLeft cancelAnimationFrame(raf); raf = requestAnimationFrame(update); } function end() { slider.classList.remove('active'); container.removeEventListener('pointermove',move); container.removeEventListener('pointerup',end); container.removeEventListener('pointerleave',end); } function activate(e) { e.preventDefault(); slider.classList.add('active'); startX = e.layerX; endX = e.layerX; startLeft = container.scrollLeft; endLeft = container.scrollLeft; container.addEventListener('pointermove',move,false); container.addEventListener('pointerup',end,false); container.addEventListener('pointerleave',end,false); } container.addEventListener('pointerdown',activate,false);
内容的提问来源于stack exchange,提问作者noirsociety
相关产品推荐
相关产品推荐

