I'm trying to make a slider in javascript with canvas. The moveSlider() function is called by 'pointermove' eventlistener, and it changes the X coordinate of a rectangle stored in 'Slider' object in 200 pixel range.
I want it to be done in 11 steps, and cant seems to figure out how.
Also for some reason, if I add value of 'delta' to Slider.x the slider moves the opposite direction of the mouse, why?
any help is appreciated.
var startPos = e.clientX
function moveSlider(e) {
let x = ctx.canvas.width / 2
let delta = startPos - e.clientX;
startPos = e.clientX;
Slider.x -= delta;
Slider.x = Slider.x > x+100 ? x+100 : Slider.x;
Slider.x = Slider.x < x-100 ? x-100 : Slider.x;
}
I'm trying to make a slider in javascript with canvas. The moveSlider() function is called by 'pointermove' eventlistener, and it changes the X coordinate of a rectangle stored in 'Slider' object in 200 pixel range.
I want it to be done in 11 steps, and cant seems to figure out how.
Also for some reason, if I add value of 'delta' to Slider.x the slider moves the opposite direction of the mouse, why?
any help is appreciated.
var startPos = e.clientX
function moveSlider(e) {
let x = ctx.canvas.width / 2
let delta = startPos - e.clientX;
startPos = e.clientX;
Slider.x -= delta;
Slider.x = Slider.x > x+100 ? x+100 : Slider.x;
Slider.x = Slider.x < x-100 ? x-100 : Slider.x;
}
Share
Improve this question
asked Mar 16 at 23:20
NahNah
431 silver badge9 bronze badges
2
|
2 Answers
Reset to default 1You can try setting up an array that contains the "snap to" X-values along the slider. You will also need a function that accepts an X value, and returns the closest "snap to" value. Something like this:
const left = 100;
const width = 200;
const numStops = 11;
const lerp = (from, to, pct) => (to - from) * pct + from;
const sliderPositions = Array.from(
{length: numStops},
(_, i) => lerp(left, left + width, i / (numStops - 1))
);
const getClosestSliderPosition = xPos =>
sliderPositions.reduce((acc, el) => {
if (Math.abs(xPos - el) < Math.abs(xPos - acc))
acc = el;
return acc;
});
console.log(getClosestSliderPosition(150));
console.log(getClosestSliderPosition(115));
console.log(sliderPositions);
Then in your event handler you can use the getClosestSliderPosition function like so:
function moveSlider(e) {
Slider.x = getClosestSliderPosition(e.clientX);
}
Canvas is fixed in px as you are already aware. If you want to streamline your code why not base it on:
e.pageX
: The horizontal coordinate of your mouse in relation to the left edge of the document.The offset between the left edge of the document and the left edge of the area within the canvas (not the offset of the whole canvas).
The offset between the left edge of the document and the right edge of the area within the canvas.
In the example below, the area within the canvas is the red line which starts 60px from the left edge of the document and its right edge is 260px from the left edge of the document. The essential lines of the "pointermove" event handler are:
if (dragging && e.pageX < 260 && e.pageX > 59) {
x = e.pageX;
draw();
const cvs = document.getElementById("cvs");
const ctx = cvs.getContext("2d");
const xpx = document.getElementById("xpx");
const xpc = document.getElementById("xpc");
const w = 220;
const h = 30;
let dragging = false;
let x = 60;
let rAF;
const rect = (x, y, w, h) => {
ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.closePath();
ctx.fill();
}
const clear = () => {
ctx.clearRect(50, 50, w, h);
}
const draw = () => {
clear();
ctx.fillStyle = "#CCCCCC";
rect(50, 50, w, h);
ctx.fillStyle = "#FF0000";
rect(60, 60, 200, 10);
ctx.fillStyle = "#444444";
rect(x - 5, 60, 10, 10);
if (dragging) {
rAF = requestAnimationFrame(draw);
}
cancelAnimationFrame(rAF);
};
const pointerMove = (e) => {
if (dragging && e.pageX < 260 && e.pageX > 59) {
x = e.pageX;
draw();
cvs.style.cursor = "ew-resize";
xpx.value = Math.ceil(x) + "px";
xpc.value = Math.ceil(((x - 60) / 200) * 100) + "%";
}
};
const pointerDown = (e) => {
if (e.pageX < 260 && e.pageX > 59) {
x = e.pageX;
dragging = true;
cvs.onpointermove = pointerMove;
cvs.style.cursor = "ew-resize";
xpx.value = Math.ceil(x) + "px";
xpc.value = Math.ceil(((x - 60) / 200) * 100) + "%";
}
};
const pointerClick = (e) => {
if (e.pageX < 260 && e.pageX > 59) {
x = e.pageX;
}
};
const pointerExit = () => {
dragging = false;
cvs.onpointermove = null;
cvs.style.cursor = "default";
};
cvs.onpointerdown = pointerDown;
cvs.onclick = pointerClick;
cvs.onpointerup = pointerExit;
draw();
* {
margin: 0;
padding: 0;
box-sizing: border-box
}
<canvas id="cvs" width="275" height="90"></canvas>
<output id="xpx"></output>
<output id="xpc"></output>
Slider.x -= delta;
try adding it:Slider.x += delta;
– zer00ne Commented Mar 17 at 0:40let delta = startPos - e.clientX
– James Commented Mar 17 at 2:15