在画布上绘制多边形形状并允许工具提示

时间:2014-03-02 16:00:09

标签: javascript html5-canvas

这基本上是我的要求,而不是问题,我必须在画布上绘制多边形(与绘画相同),但是我坚持我的要求,我必须显示工具提示悬停在绘制的每个多边形上。我知道对于像矩形这样的形状,我可以更容易地使用简单的for循环管理坐标,但是如何处理多边形。它甚至可能吗? 下面是我绘制多边形的代码

    var startPointX = "", startPointY = "", endpointX, endpointY, isnewShape = false;
tools.polygon = function () {
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) {
        tool.started = true;
        tool.x0 = ev._x;
        tool.y0 = ev._y;

        if ((Math.abs(startPointX - ev._x) < 5) && (Math.abs(startPointY - ev._y) < 5) && (startPointX != ev._x && startPointY != ev._y) && !isnewShape) {
            alert('point matched');
            startPointX = "";
            startPointY = "";
            isnewShape = true;
            context.clearRect(0, 0, canvas.width, canvas.height);

            context.beginPath();
            context.moveTo(endpointX, endpointY);

            context.lineTo(ev._x, ev._y);
            endpointX = ev._x;
            endpointY = ev._y;
            context.stroke();
            context.closePath();
            img_update();
            tool.started = false;
        }
        else {
            //                console.log(isnewShape);

            if (startPointX == "" || startPointY == "")
                return;

            context.clearRect(0, 0, canvas.width, canvas.height);

            context.beginPath();
            context.moveTo(endpointX, endpointY);
            isnewShape = false;
            context.lineTo(ev._x, ev._y);
            endpointX = ev._x;
            endpointY = ev._y;
            context.stroke();
            context.closePath();
            img_update();
        }

    };

    this.mousemove = function (ev) {
        if (!tool.started) {
            return;
        }
        // console.log('mousemove');
        context.clearRect(0, 0, canvas.width, canvas.height);

        context.beginPath();
        context.lineTo(ev._x, ev._y);
        endpointX = ev._x;
        endpointY = ev._y;
        context.stroke();
        context.closePath();
    };

    this.mouseup = function (ev) {
        if (tool.started) {

            if (startPointX == "" && startPointY == "") {

                startPointX = tool.x0;
                startPointY = tool.y0;

           }

            tool.started = false;
            img_update();
        }
    };
};

2 个答案:

答案 0 :(得分:2)

除了维护用户看到的画布外,还要在隐藏的第二个画布上绘制所有内容。重要的是每个多边形应该是自己的颜色。它不一定是人类可区分的 - 您可以将第一个绘制为#000000,将第二个#000001绘制,等等。这为1600万个多边形提供了支持 - 应该足够了!

然后,当用户将鼠标移到画布上时,找出鼠标的位置并查看隐藏画布上的颜色。这将告诉您正在徘徊的形状,您可以采取相应的行动。

答案 1 :(得分:1)

您可以使用canvas的内置命中测试方法:context.isPointInPath(x,y);

isPointInPath将测试x,y是否在最近定义的路径中。

它的工作原理如下:

据推测,您有定义每个多边形的坐标

// create an object holding all polygon points

var triangle=[{x:100,y:50},{x:150,y:100},{x:50,y:100}];

要进行命中测试,首先要重新定义三角形:

// define the polygon

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

然后使用isPointInPath检查是否有任何x,y在重新定义的三角形内

console.log( ctx.isPointInPath(mouseX,mouseY); );

以下是示例代码和演示:http://jsfiddle.net/m1erickson/d3kdf/

<!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(){

    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;
    var scrollX=$canvas.scrollLeft();
    var scrollY=$canvas.scrollTop();

    var $results=$("#results");

    // create an object holding all polygon points
    var triangle=[{x:100,y:50},{x:150,y:100},{x:50,y:100}];

    // draw the polygon
    define(triangle);
    ctx.fill();

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


    function hitTest(polygon){
        // redefine the polygon
        // (necessary to isPointInPath to work
        define(polygon);
        // ask isPointInPath to hit test the mouse position
        // against the current path
        return(ctx.isPointInPath(mouseX,mouseY));
    }

    function handleMouseMove(e){
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // check if the mouse is inside the polygon
      var isInside=hitTest(triangle);
      if(isInside){
          $results.text("Mouse is inside the Triangle");
      }else{
          $results.text("Outside");
      }

    }

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

}); // end $(function(){});
</script>
</head>
<body>
    <p id="results">Hit results</p>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>