线性插值(lerp)在可拖动滑块上不起作用



我最近正在学习"线性插值";,它创造宽松的能力。然而,可拖动滑块的放松部分似乎正在工作……但是,我无法将滑块拖过第三张幻灯片。似乎有某种惯性促使滑块反弹回第一张滑块。

<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; }

JS

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);

如果我去掉下面这行带有" ler"的代码,那么滑块就会像预期的那样工作,而不需要缓和。

startX = lerp(startX,endX,0.05);
我似乎无法完全理解这个问题。有人能告诉我正确的方向吗?如有任何反馈,将不胜感激。

更新:

终于想通了:

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);

我相信我发现了这个问题,当任何给定的"值";在lerp中给出,它总是从它的值乘以0.05移动到0。在此之后,我们需要添加滑块在一个方向上移动的总距离

const lerp = (min, max, value) => (max - min) * value + min;
function update() {
startX = lerp(startX,endX,);
const dist = endX - startX;
slider.scrollLeft = initLeft - dist;
requestAnimationFrame(update);
}

滑动条将始终默认为起始位置。尝试修改lerp常数,以在乘以"值"后添加移动的距离。它已经被定义为"dist"

最新更新