Task: create volume range slider, when you click on the scale, it should be painted over to the level at which the user clicked the mouse.
I can't use input type range for this task.
HTML
<body>
<div >
<div >
<div >
<div >-</div>
<div ></div>
<div > </div>
</div>
<div >100%</div>
</div>
</div>
<script src="script.js"></script>
</body>
JS
const buttons = document.querySelectorAll(".button");
const percent = document.querySelector(".value");
const volumeBar = document.querySelector(".volume-bar");
buttons.forEach((a_button) => {
a_button.addEventListener("click", () => {
one_step_change(a_button.innerHTML);
});
});
function one_step_change(sign) {
perc_value = Number(
percent.innerHTML.substring(0, percent.innerHTML.length - 1)
);
if (sign == " " && perc_value < 100) {
percent.innerHTML = perc_value 1 "%";
} else if (perc_value > 0) {
percent.innerHTML = perc_value - 1 "%";
}
}
volumeBar.addEventListener("click", volumeBarHandler);
function volumeBarHandler(event) {
console.log(event);
}
What I need to use for this task?
CodePudding user response:
I'm adding one example which I created to demonstrate how you can do this. Right now I have used hard coded values, you can modify it according to your needs. My main goad is just to given you one example so that you can try it out.
My Idea here is:
We should have one div #slider
, and it contains two more divs one to show some colour div #vol_level
to show this is level of volume, and one to show empty area left div #empty
.
And when user clicks on div #slider
, we find the location of click and change the width of div #vol_level
and div #empty
accordingly.
<!DOCTYPE html>
<html>
<head>
<style>
#slider {
height: 20px;
width: 300px;
display:inline-block;
float: left;
}
#vol_level {
height: 100%;
width: 0;
background: green;
float: left;
}
#empty {
height: 100%;
width: 100%;
background: lightgray;
float: left;
}
</style>
</head>
<body>
<div>
<h1>Volume Slider</h1>
<p>Current volume Level: <span id="vol_text">0%</span> </p>
<div id="slider">
<div id="vol_level"></div>
<div id="empty"></div>
</div>
<div>
<script>
var volumeLevel = document.getElementById("vol_level")
var empty = document.getElementById("empty")
var slider = document.getElementById("slider")
var text = document.getElementById("vol_text")
slider.addEventListener("click", volumeChange);
function volumeChange(e) {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - slider.style.left;
volumeLevel.setAttribute("style",`width:${x}px`);
empty.setAttribute("style",`width:${300 - x}px`);
var calc = (1.0 * x) / (300.0) * 100;
text.innerHTML = `${Math.trunc(calc)}%`;
}
</script>
</body>
</html>
Hope this helps. You can comment if you face any problem or have some doubts.
CodePudding user response:
I think this is how the code should be done. There is room for improvement like listening for minus or plus button hold or clicking and scrolling the volume bar, but I leave that for you. The current code should get you in the right direction :)
let percentValue = 100;
const buttons = document.querySelectorAll(".button");
const percent = document.querySelector(".value");
const volumeBar = document.querySelector(".volume-bar");
buttons.forEach((button) => {
button.addEventListener("click", buttonClick);
});
function buttonClick(event) {
let sign = event.currentTarget.innerHTML;
if (sign == " ")
percentValue ;
else if(sign == "-")
percentValue--;
if(percentValue < 0)
percentValue = 0;
if(percentValue > 100)
percentValue = 100;
updatePercent();
}
volumeBar.addEventListener("click", volumeBarHandler);
function volumeBarHandler(event) {
let rect = event.currentTarget.getBoundingClientRect();
let x = event.clientX - rect.left; // x position within the element
percentValue = Math.round((x / rect.width) * 100);
updatePercent();
}
function updatePercent(){
let currentPercentString = percentValue "%";
percent.innerHTML = currentPercentString;
volumeBar.style.background = `linear-gradient(90deg, red 0%, red ${currentPercentString}, gray ${currentPercentString},gray 100%)`;
}
.flex {
display: flex;
gap: 5px;
}
.volume-level-block {
display: flex;
gap: 10px;
}
.button {
cursor: pointer;
}
.volume-bar{
width: 170px;
height: 20px;
background-color: red;
}
<div >
<div >
<div >
<div >-</div>
<div ></div>
<div > </div>
</div>
<div >100%</div>
</div>
</div>
CodePudding user response:
here's my idea for your slider. to adjust the slider, set value to custom css property --volume-value
by using volumeBar.style.setProperty("--volume-value", "/* value in percentage */")
.
.volume-bar {
position: relative;
height: 10px;
background-color: lightgray;
border-radius: 10px;
}
.volume-track {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: var(--volume-value, 0);
background-color: gray;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
.volume-handle {
position: absolute;
top: 50%;
left: var(--volume-value, 0);
transform: translate(-50%, -50%);
width: 12px;
height: 12px;
border-radius: 50%;
background-color: white;
border: 8px solid gray;
}
<br><br>
<div style="width: 80%; margin: 0 auto;">
<div style="--volume-value: 50%">
<div ></div>
<span ></span>
</div>
</div>