admin管理员组

文章数量:1316841

I have an HTML canvas with all different shapes of all different sizes and it is built by parsing information from an external file. I am wondering how I can make it so that hovering the mouse over each shape will display its unique name. I have found resources on how to display text on a mouse hover for the whole canvas, but I need each individual shape to display a unique text. Thanks!

I have an HTML canvas with all different shapes of all different sizes and it is built by parsing information from an external file. I am wondering how I can make it so that hovering the mouse over each shape will display its unique name. I have found resources on how to display text on a mouse hover for the whole canvas, but I need each individual shape to display a unique text. Thanks!

Share Improve this question asked Jun 11, 2015 at 19:43 MikeMike 331 silver badge8 bronze badges 2
  • Here's an option: stackoverflow./a/1221514/4533609 – Scheda Commented Jun 11, 2015 at 19:47
  • Here is a possible option as well with support for isPointInPath and pixel detection of text letters: stackoverflow./questions/18935737/text-collision-detection/… – user1693593 Commented Jun 11, 2015 at 20:48
Add a ment  | 

2 Answers 2

Reset to default 6

You can use context.isPointInPath to test if your mouse is hovering over one of your shapes.

  1. Create a javascript object representing each shape from the external file.

    var triangle={
        name:'triangle',
        color:'skyblue',
        points:[{x:100,y:100},{x:150,y:150},{x:50,y:150}]
    };
    
  2. Create a function that takes a shape-object and makes a Path from that shape-object:

    function defineShape(s){
        ctx.beginPath();
        ctx.moveTo(s[0].x,s[0].y);
        for(var i=1;i<s.length;i++){
            ctx.lineTo(s[i].x,s[i].y);
        }
        ctx.closePath();
    }
    
  3. Use context.isPointInPath to test if the mouse is inside the most recently defined path (from step#2).

    // define the path to be tested
    defineShape(triangle);
    
    // test if the mouse is inside that shape
    if(context.isPointInPath(mouseX,mouseY){
        // the mouse is inside the shape
    }
    

Here's example code and a Demo:

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(); }

ctx.font='14px verdana';

var shapes=[];

var triangle1={
  name:'triangle1',
  color:'skyblue',
  drawcolor:'skyblue',
  points:[{x:100,y:100},{x:150,y:150},{x:50,y:150}]
};

var triangle2={
  name:'triangle2',
  color:'palegreen',
  drawcolor:'palegreen',
  points:[{x:220,y:100},{x:270,y:150},{x:170,y:150}]
};

shapes.push(triangle1,triangle2);

$("#canvas").mousemove(function(e){handleMouseMove(e);});

drawAll();

function drawAll(){
  for(var i=0;i<shapes.length;i++){
    var s=shapes[i];
    defineShape(s.points);
    ctx.fillStyle=s.drawcolor;
    ctx.fill();
    ctx.stroke();
    if(s.color!==s.drawcolor){
      ctx.fillStyle='black';
      ctx.fillText(s.name,s.points[0].x,s.points[0].y);
    }
  }
}


function defineShape(s){
  ctx.beginPath();
  ctx.moveTo(s[0].x,s[0].y);
  for(var i=1;i<s.length;i++){
    ctx.lineTo(s[i].x,s[i].y);
  }
  ctx.closePath();
}

function handleMouseMove(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // clear the canvas
  ctx.clearRect(0,0,cw,ch);

  for(var i=0;i<shapes.length;i++){
    var s=shapes[i];

    // define the shape path we want to test against the mouse position
    defineShape(s.points);
    // is the mouse insied the defined shape?
    if(ctx.isPointInPath(mouseX,mouseY)){
      // if yes, fill the shape in red
      s.drawcolor='red';
    }else{
      // if no, fill the shape with blue
      s.drawcolor=s.color;
    }

  }

  drawAll();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Hover the mouse over the shape.</h4>
<canvas id="canvas" width=300 height=300></canvas>

Are you willing to use a library, or are you attached to a purely native canvas implementation? With purely native canvas, this could get quite annoying, because you would have to not only get the mouse coordinates of the pointer, but also keep track of the position of every object and check whether or not the mouse is at that position every time the mouse moves. I coded that functionality once, and it was annoying enough with just a few rectangles to keep track of.

On the other hand, if you use KineticJS to do your canvas drawing (or presumably others; KineticJS is just the one I've used), all that annoyance is handled for you. The objects you create and add to the canvas can have event handlers attached to them using the KineticJS library, and it will be only minimally harder than reacting to mouseover events on any other HTML element. This link shows how to do it.

http://www.html5canvastutorials./kineticjs/html5-canvas-listen-or-dont-listen-to-events-with-kineticjs/

本文标签: javascriptHTML Canvas Hover TextStack Overflow