You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

拖拽滑块中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:55:32