最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript range slider with steps in html5 canvas - Stack Overflow

programmeradmin1浏览0评论

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>

发布评论

评论列表(0)

  1. 暂无评论