Recently, I've been delving into the world of "linear interpolation" and its application in creating easing effects. However, while the easing functionality of the draggable slider seems to be operational, I'm encountering an issue. The slider refuses to move past the 3rd slide, displaying a peculiar inertia that causes it to bounce back to the 1st slide.
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; }
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);
If I was to take out the following line of code with the "lerp", then the slider will work as intended without the easing.
startX = lerp(startX,endX,0.05);
I can't seem to wrap my head around this problem. Can someone please help point me in the right direction? Any feedback will be greatly appreciated.
UPDATE:
Finally figured it out:
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);