admin管理员组

文章数量:1391918

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
  • It looks as if you're subtracting the value of delta: Slider.x -= delta; try adding it: Slider.x += delta; – zer00ne Commented Mar 17 at 0:40
  • Because this subtraction is backwards: let delta = startPos - e.clientX – James Commented Mar 17 at 2:15
Add a comment  | 

2 Answers 2

Reset to default 1

You 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:

  1. e.pageX: The horizontal coordinate of your mouse in relation to the left edge of the document.

  2. 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).

  3. 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>

本文标签: javascript range slider with steps in html5 canvasStack Overflow