Draggable slider not functioning properly with linear interpolation

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

Answer №1

After some investigation, I have identified the root cause of the issue. In a lerp function, when a "value" is inputted, it will consistently multiply by 0.05 to transition toward 0 from its initial value. To resolve this, we must also factor in the total distance that the slider has moved in one direction.

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

As a result, the slider always reverts back to its starting position. To address this, consider adjusting the lerp constant to include the distance moved after multiplying by the predefined "dist" variable representing the distance.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Design a unique input component tailored specifically for react-day-picker

While working on a custom Material UI component for DayPickerInput, I encountered an issue where the onDayChange event triggers an error. handleToDateChange = (selectedDay, modifiers, dayPickerInput) => { const val = dayPickerInput.getInput().value ...

Popup Triggered by a JavaScript Timer

Seeking assistance in creating a straightforward timer-based popup. Once the timer hits 10 seconds, the popup should become visible. The timer should pause or stop, and after clicking the 'ok' button on the popup, the timer should reset to 0. Can ...

Is there a way to adjust the contrast of an image using an HTML slider and JavaScript without utilizing the canvas element?

Looking to develop a slider with HTML and JavaScript (or jQuery, CSV,...) that can adjust the contrast of an image, similar to this topic. However, I would prefer not to utilize Canvas in HTML5 for this project. Any suggestions on how to achieve this with ...

Access the hyperlink contained within the table

Having trouble clicking a navigation link inside a table? I've tried: getElementByID getElementsByClassName getElementsByTagName but none seem to be working. When using the following code: Set tbls = HTMLDoc.getElementByID("tabToggleTable") it r ...

Encountering an issue while running Angular 2 and Node.js server with the command 'npm

I encountered an issue while trying to run the project in production, After executing npm run build: prod, the compilation is error-free. However, when I run npm run server: prod, I encounter the following problem: C:\Users\Test\Project> ...

Tips for showing multiple autocomplete entries in a text box following a successful AJAX request

I'm having an issue with my code where the autocomplete multiple values, successfully retrieved by Ajax, are not being displayed. Here is the HTML I am using for display: <input type="text" name="s_to" id="s_to" class="controls"> Here is my jQ ...

I'm curious if there is a contemporary alternative to "Deep Zoom Composer" in Silverlight that enables the creation of panoramic images by stitching multiple images together

There was a time when Silverlight offered a feature known as "deep zoom", which cleverly adjusted bandwidth usage as the user zoomed in and out. Recently, I discovered a unique application for this technology - by incorporating images taken from a hot air ...

The CSS :first-child selector appears to be malfunctioning with the majority of elements

Having some difficulty with the :first-child selector. It just won't cooperate in my code. The goal is to execute a simple transform on two elements using the :first-child, but it's failing in multiple instances. Let me explain: First scenario: ...

Exploring nodes with the help of Cheerio JS

In my HTML code, I am using the Snekfetch library to fetch data. Here is a snippet of the code: <div class="entry-content"> <h4>today's date etc etc</h4> <h3>category name 1</h3> <p> <img class=" ...

The empty string is not getting recognized as part of an array

Currently, I have a textarea field where pressing enter submits and creates a new item in the array. Pressing shift + enter creates a new line in the textarea input field. But when trying to submit by pressing shift and enter after creating a new line, it ...

Implement custom styles to enhance the appearance of users' Magento websites

Is it possible to add additional CSS only to users/customers who are logged into our webshop? If so, how should I go about it - through XML or PHTML? Stian ...

Struggling with converting 11-line toy neural network code into JavaScript

I'm preparing to deliver a brief presentation on neural networks this coming Tuesday to my fellow web developer students. My plan was to convert this code (found under Part 1, a tiny toy neural network: 2 layer network) into JavaScript so that it woul ...

importing files from Uploadcare using ngCordova MediaFile

I am facing an issue while attempting to upload a sound file from ngCordova's $cordovaCapture service to UploadCare. The `uploadcare.fileFrom('object')` function is failing with an 'upload' error even though I have set the public k ...

Ajax fails to send requests to PHP after changing the URL directory

After struggling to find a solution to my query, I have come to the realization that it has not been asked before. Despite enabling rewrite rules on my apache2 server in the .htaccess file located in the root directory, I am facing an issue with my ajax sc ...

Tips for Showing Empty Data in a Nonexistent `<td>` Element within a Table

This particular query appears to be quite simple... I am seeking the HTML code for creating a table: <table> <tr> <th>Heading 1</th> <td>or</td> <th>Heading 2</th> </tr> <tr> ...

Display the HTML content retrieved from the SailsJS Controller

Exploring the world of SailsJS, I am on a mission to save HTML content in a database, retrieve it, and display it as rendered HTML. To achieve this goal, I have set up a sails model and a controller. This is what my model looks like: attributes: { ht ...

Experiment with erroneous scenarios using React, Jest, and React-Testing-Library

I've encountered an issue with a React component that triggers an Error when there is faulty programming. Specifically, the Component requires a prop called data, and I have the following code snippet in place to check for its existence: if (!data) { ...

Automating image uploads with Selenium and Python even when the element appears hidden

Recently, I've encountered an issue while trying to upload photos using Selenium with Python. The input element appears to be hidden on the page, causing errors when using the .sendkeys method. Here is the HTML code for the input element: <div d ...

Protractor experiencing difficulty in adjusting price slider

As a newcomer to protractor, I am attempting to test a price slider that sorts products based on the provided price range. Unfortunately, I am facing difficulty in dragging the slider (min point) using protractor. Can anyone provide guidance on how to move ...

Newspaper-style text layout with Bootstrap columns

I'm currently working on a WordPress project and I've been attempting to create a smooth text flow between columns using the Bootstrap framework. What I'm aiming for is to have the same story seamlessly transition from one column to another ...