检测鼠标是否在画布内的对象上

时间:2014-06-04 17:37:19

标签: javascript html5 html5-canvas mouseover mouseout

我在canvas元素中创建了一条线。我正在寻找最简单的方法来检测鼠标的位置是否在画布内部的行内。

我已经使用这个函数来查看画布中鼠标的位置,但我对如何继续操作感到很困惑。

function getMousePos(c, evt) {
            var rect = c.getBoundingClientRect();
            return {
                x: evt.clientX - rect.left,
                y: evt.clientY - rect.top
            };
        }

我也查看了这个主题Fabricjs detect mouse over object path,但它检测到鼠标是否在画布内,而不是在对象内部。

我创建的行是较小行的一部分,彼此连接。

 for (var i = 0; i < 140 ; i++) {

                ctx.beginPath();

                ctx.moveTo(x[i],y[i]);
                ctx.quadraticCurveTo(x[i],50,x[i+1],y[i+1]);
                ctx.lineWidth = 40;

                ctx.strokeStyle = 'white';
                ctx.lineCap = 'round';
                ctx.stroke();

            }

其中x [i]和y [i]是具有我想要的坐标的数组。

我希望我的问题很清楚,虽然我对javascript不是很熟悉。

由于 迪米特拉

1 个答案:

答案 0 :(得分:11)

演示:http://jsfiddle.net/m1erickson/Cw4ZN/

enter image description here enter image description here

您需要这些概念来检查鼠标是否在一行内:

  • 定义起点&amp;一行的终点

  • 收听鼠标事件

  • 在鼠标移动时,检查鼠标是否在行的指定距离内

这是一个带注释的示例代码供您学习。

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    // canvas related variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    // dom element to indicate if mouse is inside/outside line
    var $hit=$("#hit");

    // determine how close the mouse must be to the line
    // for the mouse to be inside the line
    var tolerance=5;

    // define the starting & ending points of the line
    var line={x0:50,y0:50,x1:100,y1:100};

    // set the fillstyle of the canvas
    ctx.fillStyle="red";

    // draw the line for the first time
    draw(line);

    // function to draw the line
    // and optionally draw a dot when the mouse is inside
    function draw(line,mouseX,mouseY,lineX,lineY){
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.beginPath();
        ctx.moveTo(line.x0,line.y0);
        ctx.lineTo(line.x1,line.y1);
        ctx.stroke();
        if(mouseX && lineX){
            ctx.beginPath();
            ctx.arc(lineX,lineY,tolerance,0,Math.PI*2);
            ctx.closePath();
            ctx.fill();
        }
    }

    // calculate the point on the line that's 
    // nearest to the mouse position
    function linepointNearestMouse(line,x,y) {
        //
        lerp=function(a,b,x){ return(a+x*(b-a)); };
        var dx=line.x1-line.x0;
        var dy=line.y1-line.y0;
        var t=((x-line.x0)*dx+(y-line.y0)*dy)/(dx*dx+dy*dy);
        var lineX=lerp(line.x0, line.x1, t);
        var lineY=lerp(line.y0, line.y1, t);
        return({x:lineX,y:lineY});
    };

    // handle mousemove events
    // calculate how close the mouse is to the line
    // if that distance is less than tolerance then
    // display a dot on the line
    function handleMousemove(e){
      e.preventDefault();
      e.stopPropagation();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      if(mouseX<line.x0 || mouseX>line.x1){
          $hit.text("Outside");
          draw(line);
          return;          
      }
      var linepoint=linepointNearestMouse(line,mouseX,mouseY);
      var dx=mouseX-linepoint.x;
      var dy=mouseY-linepoint.y;
      var distance=Math.abs(Math.sqrt(dx*dx+dy*dy));
      if(distance<tolerance){
          $hit.text("Inside the line");
          draw(line,mouseX,mouseY,linepoint.x,linepoint.y);
      }else{
          $hit.text("Outside");
          draw(line);
      }
    }

    // tell the browser to call handleMousedown
    // whenever the mouse moves
    $("#canvas").mousemove(function(e){handleMousemove(e);});

}); // end $(function(){});
</script>
</head>
<body>
    <h2 id="hit">Move mouse near line</h2>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

关于命中测试路径:

如果使用路径命令创建路径,则可以使用context.isPointInPath(mouseX,mouseY)检查鼠标是否在路径中。 context.isPointInPath不适用于行,但因为理论上线条的宽度为零而无法“击中”。