Canvas 上的范围输入

Range input on Canvas

我正在尝试在 canvas 元素上创建一个范围滑块,它会返回一个值,然后我可以使用该值来操作 canvas 元素。它需要位于 canvas 内,因为它用于 html5 横幅广告。我知道我无法将 DOM 元素插入 canvas 中,所以我想知道是否有用于使用 canvas?

创建范围滑块的库或插件

我想要做的是使用范围滑块操纵图像在 canvas 上的位置。即当滑块向右移动时,图像位置向左移动,反之亦然。我知道我可以使用输入滑块来执行此操作,但在 canvas 本身上创建滑块时遇到问题。

您的范围控件很容易在本地创建——尤其是当您的范围控件水平或垂直对齐时。

创建一个非常简单的水平范围控件

给定范围控制的这些值:

  • 条的起始位置:x,y,
  • 条的宽度:width,
  • 拇指的高度:height,
  • 当前拇指位置以百分比表示:pct

显示范围控制:

  • 绘制范围条:[x,y][x+width, y] 之间的水平线。
  • 绘制范围缩略图:[x+width*pct, y-height/2][x+width*pct, y+height/2] 之间的垂直线。

设置拇指位置:

  1. 侦听 mousemove 事件并获取当前 mouseX 位置。
  2. 使用当前鼠标位置计算鼠标在范围条的开始和结束之间的百分比:pct=(mouseX-x)/width 其中 mouseX 被限制在 xx+width 之间。
  3. 使用新计算的缩略图百分比重新显示范围。

使用pct计算范围控制值:value=minValue+(maxValue-minValue)*pct.

非轴对齐范围控件

如果您的范围控件未水平或垂直放置,您将需要计算栏上离鼠标最近的点。然后,您必须计算该点在范围栏的起点和终点之间的百分比距离。前面的 展示了如何找到距离当前鼠标位置最近的直线(line==range bar)上的点。

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

var isDown=false;

var range=makeRangeControl(50,40,200,25);
drawRangeControl(range);

canvas.onmousedown=(function(e){handleMouseDown(e);});
canvas.onmousemove=(function(e){handleMouseMove(e);});
canvas.onmouseup=(function(e){handleMouseUpOut(e);});
canvas.onmouseout=(function(e){handleMouseUpOut(e);});


function makeRangeControl(x,y,width,height){
    var range={x:x,y:y,width:width,height:height};
    range.x1=range.x+range.width;
    range.y1=range.y;
    //
    range.pct=0.50;
    return(range);
}

function drawRangeControl(range){
    // clear the range control area
    
    // bar
    ctx.lineWidth=6;
    ctx.lineCap='round';
    ctx.beginPath();
    ctx.moveTo(range.x,range.y);
    ctx.lineTo(range.x1,range.y);
    ctx.strokeStyle='black';
    ctx.stroke();
    // thumb
    ctx.beginPath();
    var thumbX=range.x+range.width*range.pct;
    ctx.moveTo(thumbX,range.y-range.height/2);
    ctx.lineTo(thumbX,range.y+range.height/2);
    ctx.strokeStyle='rgba(255,0,0,0.25)';
    ctx.stroke();
    // legend
    ctx.fillStyle='blue';
    ctx.textAlign='center';
    ctx.textBaseline='top';
    ctx.font='10px arial';
    ctx.fillText(parseInt(range.pct*100)+'%',range.x+range.width/2,range.y-range.height/2-2);
}

function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // get mouse position
  var mx=parseInt(e.clientX-offsetX);
  var my=parseInt(e.clientY-offsetY);
  // test for possible start of dragging
  isDown=(mx>range.x && mx<range.x+range.width && my>range.y-range.height/2 && my<range.y+range.height/2);
}

function handleMouseUpOut(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // stop dragging
  isDown=false;
}

function handleMouseMove(e){
  if(!isDown){return;}
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // get mouse position
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  // set new thumb & redraw
  range.pct=Math.max(0,Math.min(1,(mouseX-range.x)/range.width));
  ctx.clearRect(range.x-12.5,range.y-range.height/2-15,range.width+25,range.height+20);
  drawRangeControl(range);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Drag the thumb on the range control</h4>
<canvas id="canvas" width=512 height=512></canvas>