简体   繁体   中英

How to select HTML5 canvas shapes?

I have a HTML5 canvas on which I have drawn several shapes.

What I want to happen, is that when the mouse is clicked on any shape the shape should get selected (at least it can tell what kind of shape is selected).

Thank you.

Try using an existing canvas library (or create your own) that has an event when a shape is being selected.

The example below uses the Kinetic JS library , and the example below is from HTML5 Canvas Region Events Example :

var triangle = new Kinetic.Shape(function(){
    var context = this.getContext();
    context.beginPath();
    context.lineWidth = 4;
    context.strokeStyle = "black";
    context.fillStyle = "#00D2FF";
    context.moveTo(120, 50);
    context.lineTo(250, 80);
    context.lineTo(150, 170);
    context.closePath();
    context.fill();
    context.stroke();
});

triangle.on("mouseout", function(){
    writeMessage(messageLayer, "Mouseout triangle");
});

triangle.on("mousemove", function(){
    var mousePos = stage.getMousePosition();
    var x = mousePos.x - 120;
    var y = mousePos.y - 50;
    writeMessage(messageLayer, "x: " + x + ", y: " + y);
});

shapesLayer.add(triangle);

var circle = new Kinetic.Shape(function(){
    var canvas = this.getCanvas();
    var context = this.getContext();
    context.beginPath();
    context.arc(380, canvas.height / 2, 70, 0, Math.PI * 2, true);
    context.fillStyle = "red";
    context.fill();
    context.lineWidth = 4;
    context.stroke();
});

circle.on("mouseover", function(){
    writeMessage(messageLayer, "Mouseover circle");
});
circle.on("mouseout", function(){
    writeMessage(messageLayer, "Mouseout circle");
});
circle.on("mousedown", function(){
    writeMessage(messageLayer, "Mousedown circle");
});
circle.on("mouseup", function(){
    writeMessage(messageLayer, "Mouseup circle");
});

shapesLayer.add(circle);

stage.add(shapesLayer);
stage.add(messageLayer);


In addition, I have included some mouse-in detection if the cursor is within the shape, without using any javascript libraries.

Rectangular-based mouse-in detection:

function isCursorWithinRectangle(x, y, width, height, mouseX, mouseY) {
    if(mouseX > x && mouseX < x + width && mouseY > y && mouseY < y + height) {
        return true;
    }
    return false;
}


Circle-based mouse-in detection:

function isCursorWithinCircle(x, y, r, mouseX, mouseY) {
    var distSqr = Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2);

    if(distSqr < r * r) {
        return true;
    }
    return false;
}

Canvas does not have an interface for the elements on it like the DOM. It is solely used for drawing.

You need to create your assets as objects and use a drawing loop to paint them. You then forget about the canvas element, you work with your objects, with their offsets, etc.

There's a very simple way to select complex shapes with pixel precision that doesn't involve bounding rectangles or math calculations.

The idea is that you duplicate all of your shapes onto a hidden secondary canvas, where you assign each shape a unique color. When you perform a mouseover or click event on the original canvas, you save the mouse's (x, y) coordinates in relation to the visible canvas, and then you look-up the pixel color on your hidden canvas using those same coordinates. Because each shape has a unique color on the hidden canvas, that color corresponds to the exact shape that the user selected.

Note that this only supports up to roughly 16.7 million shapes because RGB only has 24 bits of color, but that should be more than enough.

Here's a simple example using D3 and Canvas: http://bl.ocks.org/syntagmatic/6645345

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM