How to detect if mouse position is hovering

前端 未结 3 617
太阳男子
太阳男子 2021-01-07 12:52

I have this discussion which indicates how to make a pencil tool.

How can I detect whether the mouse is hovering on drawn area/points/images using the pencil tool? T

相关标签:
3条回答
  • 2021-01-07 13:09

    You can get the (per pixel) image data from a canvas: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData. Then check if the mouse is hovering over a green pixel.

    0 讨论(0)
  • 2021-01-07 13:13

    Here's a quick demo. Move your mouse within 5px of either end of the line to see the guides.

    The idea is that it uses collision detection to work out if the mouse is within 5 pixels of the start or end of the line.

    You can easily change from ugly square guides to a circle. You can essentially do what you want.

    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');
    canvas.width = 500;
    canvas.height = 400;
    document.body.appendChild(canvas);
    
    //add as many lines as you want
    var lines = [
      {start: {x: 100, y: 100}, end: {x: 200, y: 300}},
      {start: {x: 200, y: 150}, end: {x: 50, y: 250}},
      {start: {x: 240, y: 240}, end: {x: 450, y: 150}},
      {start: {x: 160, y: 340}, end: {x: 10, y: 90}},
      {start: {x: 380, y: 270}, end: {x: 300, y: 380}}
    ];
    
    function render(){
      ctx.clearRect(0,0,500,400);
      for(var c = 0; c < lines.length; c++){
        ctx.moveTo(lines[c].start.x, lines[c].start.y);
        ctx.lineTo(lines[c].end.x, lines[c].end.y);
        ctx.stroke();
      }
    }
    
    render();
    
    var mouse = {x: 0, y: 0};
    
    document.addEventListener('mousemove', function(e){
      mouse.x = e.clientX;
      mouse.y = e.clientY;
      render();
      for(var c = 0; c < lines.length; c++){
        if(
          //check if within 10px of start of line
          (mouse.x > lines[c].start.x - 5 &&
           mouse.x < lines[c].start.x + 5 &&
           mouse.y > lines[c].start.y - 5 &&
           mouse.y < lines[c].start.y + 5) ||
          //same for the end of the line
          (mouse.x > lines[c].end.x - 5 &&
           mouse.x < lines[c].end.x + 5 &&
           mouse.y > lines[c].end.y - 5 &&
           mouse.y < lines[c].end.y + 5)
        ){
          showGuides(c);
        }
      }
    });
    //function to show the guides
    function showGuides(i){
      ctx.fillRect(lines[i].start.x - 5, lines[i].start.y - 5, 10, 10);
      ctx.fillRect(lines[i].end.x - 5, lines[i].end.y - 5, 10, 10);
    }
    body{
      margin: 0;
    }

               ^ ^ ^

               |  |  |

    Run code snippet

    0 讨论(0)
  • 2021-01-07 13:20

    The only solution in your case is to save all drawn points into arrays, themselves saved in one array containing all your pathes :

    • onmousedown : create a new path array.
    • onmousemove:
      -- if drawing -> fill the currentPath's array with every drawn points.
      -- else -> check if the actual mouse coordinates are in any of your path arrays.

    var ctx = canvas.getContext("2d"),
      painting = false,
      lineThickness = 1;
    
    canvas.width = canvas.height = 600;
    
    var dCanvas = canvas.cloneNode(true);
    dCtx = dCanvas.getContext('2d');
    pCanvas = canvas.cloneNode(true);
    pCtx = pCanvas.getContext('2d');
    dCtx.fillStyle = "#FFF";
    pCtx.fillStyle = "red";
    ctx.fillRect(0, 0, 600, 600);
    
    var pathes = [],
      currentPath;
    
    canvas.onmousedown = function(e) {
      currentPath = [];
      pathes.push(currentPath);
      painting = true;
    };
    
    canvas.onmouseup = function(e) {
      painting = false;
    }
    
    canvas.onmousemove = function(e) {
      pCtx.clearRect(0, 0, canvas.width, canvas.height);
      var mouseX = e.pageX - this.offsetLeft,
        mouseY = e.pageY - this.offsetTop;
      if (painting) {   
        var lastPoint = currentPath[currentPath.length-1] || {
          x: e.pageX - canvas.offsetLeft,
          y: e.pageY - canvas.offsetTop
        };
        var x1 = mouseX,
          x2 = lastPoint.x,
          y1 = mouseY,
          y2 = lastPoint.y;
    
    
        var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
        if (steep) {
          var x = x1;
          x1 = y1;
          y1 = x;
    
          var y = y2;
          y2 = x2;
          x2 = y;
        }
        if (x1 > x2) {
          var x = x1;
          x1 = x2;
          x2 = x;
    
          var y = y1;
          y1 = y2;
          y2 = y;
        }
    
        var dx = x2 - x1,
          dy = Math.abs(y2 - y1),
          error = 0,
          de = dy / dx,
          yStep = -1,
          y = y1;
    
        if (y1 < y2) {
          yStep = 1;
        }
    
        lineThickness = 5-Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) / 10;
        if (lineThickness < 1) {
          lineThickness = 1;
        }
    
        for (var x = x1; x < x2; x++) {
          if (steep) {
            dCtx.fillRect(y, x, lineThickness, lineThickness);
            currentPath.push({x: y,y: x});
          } else {
            dCtx.fillRect(x, y, lineThickness, lineThickness);
            currentPath.push({x: x,y: y});
          }
    
          error += de;
          if (error >= 0.5) {
            y += yStep;
            error -= 1.0;
          }
        }
        currentPath.push({x: mouseX,y: mouseY});
      } else {
        pathes.forEach(function(path) {
          if (path.some(function(point) {
            return isBetween(mouseX, point.x, 5) && isBetween(mouseY, point.y, 5)
          })) {
            pCtx.beginPath();
            pCtx.arc(path[0].x+2.5, path[0].y+2.5, 5, 0, Math.PI*2);
            pCtx.fill();
    
            pCtx.beginPath();
            pCtx.arc(path[path.length-1].x+2.5, path[path.length-1].y+2.5, 5, 0, Math.PI*2);
            pCtx.fill();
          }
        });
      }
      ctx.fillRect(0, 0, 600, 600);
      ctx.drawImage(dCanvas, 0, 0);
      ctx.drawImage(pCanvas, 0, 0);
    }
    
    function isBetween(x, y, z) {
      return (x >= y - z && x <= y + z);
    }
    canvas {
      border: 1px solid
    }
    <canvas id="canvas" width="500" height="500"></canvas>

    0 讨论(0)
提交回复
热议问题