Sliders are common user interface components that allow users to select a value from a range. By adding multiple pointers to a single slider, we can provide more flexibility in selecting multiple values. Our goal is to implement a slider with three draggable pointers, each representing a specific value within the slider’s range.
We know how to make a slider of range with two pointers only by using normal HTML tags like
<input type="range" id="points" name="points" min="0" max="10">
Result of the above code :
<input type="range" class="min" min="0" max="1000" value="300" step="10">
<input type="range" class="max" min="0" max="1000" value="700" step="10">
Result of the above code :
But how to make a single slider with three pointers and four values, don’t worry here you can see the solution using normal HTML, CSS, and Javascript
Before we begin, make sure you have a basic understanding of HTML, CSS, and JavaScript. Also, ensure you have a code editor like Visual Studio Code or Sublime Text to write and test your code.
Step 1: Setting up the HTML structure
<div class="slider-container">
<div class="slider-track"></div>
<div class="slider-pointer" data-value="50" style="left: 50%;"></div>
<div class="slider-pointer" data-value="90" style="left: 90%;"></div>
<div class="slider-pointer" data-value="100" style="left: 100%;"></div>
</div>
<div class="result-container">
<div>Value 1: <span id="value1">50</span></div>
<div>Value 2: <span id="value2">40</span></div>
<div>Value 3: <span id="value3">10</span></div>
<div>Value 4: <span id="value4">0</span></div>
</div>
Step 2: Styling the slider with CSS
.slider-container {
position: relative;
width: 100%;
height: 20px;
background-color: #ddd;
}
.slider-track {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 4px;
background-color: #333;
}
.slider-pointer {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #0066cc;
cursor: pointer;
}
.result-container {
margin-top: 20px;
font-size: 16px;
}
Step 3: Implementing the JavaScript logic
const sliderContainer = document.querySelector(".slider-container");
const sliders = document.querySelectorAll(".slider-pointer");
const value1 = document.getElementById("value1");
const value2 = document.getElementById("value2");
const value3 = document.getElementById("value3");
const value4 = document.getElementById("value4");
function updateValues() {
const values = Array.from(sliders).map((slider) => Number(slider.dataset.value));
value1.textContent = values[0];
value2.textContent = values[1] - values[0];
value3.textContent = values[2] - values[1];
value4.textContent = 100 - (values[2] - values[1] + values[1] - values[0] + values[0]);
}
sliders.forEach((slider) => {
slider.addEventListener("mousedown", (e) => {
const target = e.target;
const sliderWidth = target.parentNode.offsetWidth;
let prevX = e.clientX;
function onMouseMove(e) {
const deltaX = e.clientX - prevX;
const newPosition = Math.min(Math.max(target.offsetLeft + deltaX, 0), sliderWidth);
prevX = e.clientX;
target.style.left = newPosition + "px";
target.dataset.value = Math.round((newPosition / sliderWidth) * 100);
updateValues();
}
function onMouseUp() {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
}
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
});
});
// Update the values initially
updateValues();
Results :
But how to implement the same code on Angular or React framework?
Implement code using the Angular framework.
Step 1: app.component.html code looks
<div class="slider-container">
<div class="slider-track" ></div>
<div
class="slider-pointer"
*ngFor="let slider of sliders; let i = index"
[style.left]="slider.position"
[attr.data-value]="slider.value"
(mousedown)="onDragStart($event, i)"
></div>
</div>
<div class="result-container">
<div class="easy-slider ">
<div>Easy</div>
<div>{{value1}}%</div>
</div>
<div class="medium-slider ">
<div>Medium</div>
<div>{{value2}}%</div>
</div><div class="hard-slider ">
<div>Hard</div>
<div>{{value3}}%</div>
</div>
<div class="hardest-slider ">
<div>Hardest</div>
<div>{{value4}}%</div>
</div>
</div>
Step 2: app.component.css code looks
.slider-container {
position: relative;
width: 30%;
height: 20px;
background-color: #ddd;
margin-left:200px;
margin-top:50px;
}
.slider-track {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 4px;
background-color: #333;
}
.slider-pointer {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #0066cc;
cursor: pointer;
}
.result-container {
margin-top: 20px;
font-size: 16px;
margin-left:400px;
}
.slider-container {
position: relative;
width: 30%;
height: 20px;
background-color: #ddd;
margin-left:200px;
margin-top:50px;
}
.slider-track {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 4px;
background-color: #333;
}
.slider-pointer {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #0066cc;
cursor: pointer;
}
.result-container {
margin-top: 20px;
font-size: 16px;
margin-left:400px;
}
Step 3: app.component.ts code looks
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
value1=50;
value2=40;
value3=10;
value4=0;
sliders = [
{ value: 50, position: '46%' },
{ value: 90, position: '86%' },
{ value: 100, position: '96%' }
];
constructor() {
this.onDragStart = this.onDragStart.bind(this);
}
ngOnInit(): void {}
slidersAll = [
{ position: '0%', value: this.value1 },
{ position: '25%', value: this.value2 },
{ position: '50%', value: this.value3 },
{ position: '75%', value: this.value4 },
];
getWidthForSegment(value: number): string {
const total = this.value1 + this.value2 + this.value3 + this.value4;
const widthPercentage = (value / total) * 100;
return `${widthPercentage}%`;
}
onDragStart =(event:any, index: number) => {
const target = event.target;
const sliderWidth = target.parentNode.offsetWidth;
let prevX = event.clientX;
const onMouseMove = (event:any) => {
const deltaX = event.clientX - prevX;
const newPosition = Math.min(Math.max(target.offsetLeft + deltaX, 0), sliderWidth);
prevX = event.clientX;
target.style.left = newPosition + 'px';
target.dataset.value = Math.round((newPosition / sliderWidth) * 100);
this.sliders[index].value = target.dataset.value;
this.sliders[index].position = target.style.left;
this.updateValues();
}
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
updateValues() {
const values = this.sliders.map((slider) => Number(slider.value));
this.value1 = values[0];
this.value2 = values[1] - values[0];
this.value3 = values[2] - values[1];
this.value4 = 100 - (values[2] - values[1] + values[1] - values[0] + values[0]);
}
}
Implement code using React framework:
Step 1: Create a new React component named “Slider”
import React, { useState } from 'react';
import './Slider.css';
const Slider = () => {
const [pointer1Value, setPointer1Value] = useState(50);
const [pointer2Value, setPointer2Value] = useState(90);
const [pointer3Value, setPointer3Value] = useState(100);
const [pointer1Position, setPointer1Position] = useState(pointer1Value);
const [pointer2Position, setPointer2Position] = useState(pointer2Value);
const [pointer3Position, setPointer3Position] = useState(pointer3Value);
const updateValues = () => {
const value2 = pointer2Value - pointer1Value;
const value3 = pointer3Value - pointer2Value;
const value4 = 100 - (value2 + value3);
return { value2, value3, value4 };
};
const { value2, value3, value4 } = updateValues();
const onMouseDown = (event, pointerIndex) => {
const sliderWidth = event.target.parentNode.offsetWidth;
let prevX = event.clientX;
const onMouseMove = (e) => {
const deltaX = e.clientX - prevX;
const newPosition = Math.min(Math.max(event.target.offsetLeft + deltaX, 0), sliderWidth);
prevX = e.clientX;
if (pointerIndex === 1) {
setPointer1Position(newPosition);
setPointer1Value(Math.round((newPosition / sliderWidth) * 100));
} else if (pointerIndex === 2) {
setPointer2Position(newPosition);
setPointer2Value(Math.round((newPosition / sliderWidth) * 100));
} else if (pointerIndex === 3) {
setPointer3Position(newPosition);
setPointer3Value(Math.round((newPosition / sliderWidth) * 100));
}
};
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
};
return (
<>
<div className="slider-container">
<div className="slider-track"></div>
<div
className="slider-pointer"
style={{ left: `${pointer1Position}px` }}
data-value={pointer1Value}
onMouseDown={(e) => onMouseDown(e, 1)}
></div>
<div
className="slider-pointer"
style={{ left: `${pointer2Position}px` }}
data-value={pointer2Value}
onMouseDown={(e) => onMouseDown(e, 2)}
></div>
<div
className="slider-pointer"
style={{ left: `${pointer3Position}px` }}
data-value={pointer3Value}
onMouseDown={(e) => onMouseDown(e, 3)}
></div>
</div>
<div className="result-container">
<div>Value 1: <span id="value1">{pointer1Value}</span></div>
<div>Value 2: <span id="value2">{value2}</span></div>
<div>Value 3: <span id="value3">{value3}</span></div>
<div>Value 4: <span id="value4">{value4}</span></div>
</div>
</>
);
};
export default Slider;
Step 2: Create a CSS file named “Slider.css” and add the following styles
.slider-container {
position: relative;
width: 30%;
height: 20px;
background-color: #ddd;
margin-left: 200px;
margin-top: 50px;
}
.slider-track {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 4px;
background-color: #333;
}
.slider-pointer {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #0066cc;
cursor: pointer;
}
.result-container {
margin-top: 20px;
font-size: 16px;
margin-left: 400px;
}
As you move each pointer, you will notice that the values are updated accordingly. The third pointer’s position determines the range between the first and third pointers, which is displayed as a blue track.
Congratulations! You’ve successfully created a single slider with three-pointers and four values using HTML, CSS, JavaScript, React, and Angular. This custom slider can be incorporated into various web projects to provide users with a more versatile and interactive way of selecting multiple values within a range. Feel free to enhance the design and functionality further based on your project requirements. Happy coding!
#singleslider #threepointer