【问题标题】:How set a identification to Canvas Path?如何为 Canvas Path 设置标识?
【发布时间】:2013-09-17 00:13:57
【问题描述】:

大家早上好。

我正在为我工​​作的企业系统构建一个图表,但我遇到了一个问题,我需要插入某种标识,我可能会被 JavaScript (名称、ID、标签……)。

有人可以告诉我如何分别识别图表的每个元素吗?更准确地说,我想知道每个元素 arc 是被创建的。


如果有人想查看代码以更好地理解它,我会将链接放在这里:
- JS Bin

【问题讨论】:

    标签: html canvas path html5-canvas identification


    【解决方案1】:

    您在画布上绘制的任何内容都不会自动记住或标有 id。

    所有画布绘图都成为被遗忘且无法访问的像素。但是,有一些方法可以跟踪您的各种图纸。

    与其将 posX、posY 和颜色信息保存在单独的并行数组中,不如为每个节点创建一个对象。

    然后您可以将 id 属性添加到每个节点对象:

    var nodes=[];
    
    nodes.push({id:"sun", x:100, y:100, color:"yellow"});
    nodes.push({id:"earth", x:50, y:50, color:"blue"});
    nodes.push({id:"moon", x:50, y:60, color:"gray"});
    

    当然,还要从每个节点中提取图形信息...

    您可以在函数内绘制图表,并在需要时应用 scaleFactor。

        function drawGraph(){
            context.clearRect(0,0,canvas.width,canvas.height);
            context.save();
            context.scale(scaleFactor,scaleFactor);
            for(var i=0; i<nodes.length;i++){
                var node=nodes[i];
                context.beginPath();
                context.moveTo(centerCanvasX,centerCanvasY);
                context.lineTo(node.x,node.y);
                context.stroke();
                context.beginPath();
                context.arc(node.x,node.y,node.radius,0,Math.PI*2,false);
                context.closePath();
                context.stroke();
                context.fillStyle=node.color;
                context.fill();
            }
            context.restore();
        }
    

    对于拖动/单击/等,您可以点击测试每个节点数组元素,直到找到匹配项。

    function hit(x,y){
        for(var i=0;i<nodes.length;i++){
            var node=nodes[i];
            var dx=node.x-x;
            var dy=node.y-y;
            var rr=node.radius;
            if(dx*dx+dy*dy<rr*rr){
                return(i);
            }
        }
        return(-1);
    }
    

    匹配的元素将具有您需要的 id。

    如果您的图表被缩放并且您使用鼠标坐标拖动,您必须通过图表的当前 scaleFactor 调整浏览器提供给您的坐标:

    mouseX=parseInt(event.clientX-offsetX)/scaleFactor;
    mouseY=parseInt(event.clientY-offsetY)/scaleFactor;
    

    这是代码和小提琴:http://jsfiddle.net/m1erickson/c4hsW/

    <!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; padding:20px; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var context=canvas.getContext("2d");
        var canvasOffset=$("#canvas").offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
        var centerCanvasX=canvas.width/2;
        var centerCanvasY=canvas.height/2;
    
        var startX;
        var startY;
        var isDown=false;
    
        var nodes=[];
        var dragNode;
    
        var scaleFactor=1.00;
    
        nodes.push({id:"sun", x:centerCanvasX, y:centerCanvasY, radius:20, color:"yellow"});
        nodes.push({id:"earth", x:50, y:50, radius:5, color:"blue"});
        nodes.push({id:"moon", x:50, y:65, radius:3, color:"gray"});
    
        drawGraph();
    
        function drawGraph(){
            context.clearRect(0,0,canvas.width,canvas.height);
            context.save();
            context.scale(scaleFactor,scaleFactor);
            for(var i=0; i<nodes.length;i++){
                var node=nodes[i];
                context.beginPath();
                context.moveTo(centerCanvasX,centerCanvasY);
                context.lineTo(node.x,node.y);
                context.stroke();
                context.beginPath();
                context.arc(node.x,node.y,node.radius,0,Math.PI*2,false);
                context.closePath();
                context.stroke();
                context.fillStyle=node.color;
                context.fill();
            }
            context.restore();
        }
    
        function hit(x,y){
            for(var i=0;i<nodes.length;i++){
                var node=nodes[i];
                var dx=node.x-x;
                var dy=node.y-y;
                var rr=node.radius;
                if(dx*dx+dy*dy<rr*rr){
                    return(i);
                }
            }
            return(-1);
        }
    
    
        function handleMouseDown(e){
            mouseX=parseInt(e.clientX-offsetX)/scaleFactor;
            mouseY=parseInt(e.clientY-offsetY)/scaleFactor;
    
            var i=hit(mouseX,mouseY);
            if(i>=0){ 
                startX=mouseX;
                startY=mouseY;
                isDown=true;
                dragNode=nodes[i];
            }
        }
    
        function handleMouseUp(e){
          isDown=false;
        }
    
        function handleMouseOut(e){
          isDown=false;
        }
    
        function handleMouseMove(e){
            if(!isDown){return;}
    
            // get the current mouse position
            mouseX=parseInt(e.clientX-offsetX)/scaleFactor;
            mouseY=parseInt(e.clientY-offsetY)/scaleFactor;
            // reposition the dragged node
            dragNode.x+=(mouseX-startX);
            dragNode.y+=(mouseY-startY);
            startX=mouseX;
            startY=mouseY;
            // redraw the graph
            drawGraph();
        }
    
        $("#canvas").mousedown(function(e){handleMouseDown(e);});
        $("#canvas").mousemove(function(e){handleMouseMove(e);});
        $("#canvas").mouseup(function(e){handleMouseUp(e);});
        $("#canvas").mouseout(function(e){handleMouseOut(e);});
    
        $("#bigger").click(function(){
            scaleFactor+=0.20;
            drawGraph();
        });
    
        $("#smaller").click(function(){
            scaleFactor-=0.20;
            drawGraph();
        });
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <button id="bigger">Scale Up</button>
        <button id="smaller">Scale Down</button><br>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • 我调整了您的示例以在我的代码中工作,但我最终产生了另一个问题。我需要的是一种方法来“调用”外部位置的这些节点,而不必重新创建整个图表。
    • 乐于助人...您能解释一下“从外部调用这些节点”吗?
    • 我提供的代码是对我所拥有的内容的总结。还有其他不存在的功能,伴随着用户窗口的缩放。问题是当用户调整窗口大小时,只是在上面创建了另一个图表。这是一个问题。我需要将“criaGrafico”和“events.setStage”分开。但这样做,我失去了动画。所以我需要每个节点的 ID,这样就可以从 JavaScript 调用它而无需重新创建图表。
    • 您无需调整太多即可调整图表大小。创建一个 scaleFactor 变量,您可以在窗口调整大小时对其进行调整。然后在绘制图表时使用该 scaleFactor:context.scale(scaleFactor,scaleFactor)。要将鼠标坐标与缩放图匹配,您必须将任何鼠标事件坐标除以该 scaleFactor:mouseX = event.clientX/scaleFactor。我已经编辑了我的答案以包括图形缩放。祝你的项目好运!
    • 最后一个想法...您可能会考虑使用 SVG 而不是画布。 SVG 绘图功能类似于画布,但由于 SVG 对象是真正的 html DOM 元素,它们是持久的(记住)。由于它们是持久化的,因此 SVG 对象可以具有 id、被操纵、响应事件等。
    猜你喜欢
    • 2011-06-26
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多