【问题标题】:HTML5 Canvas: Manipulating Individual PathsHTML5 Canvas:操作单个路径
【发布时间】:2013-10-28 13:53:10
【问题描述】:

在使用 HTML5 画布时,如何将特定路径保存到 javascript 变量/数组,然后再对其进行操作?到目前为止,这是我正在做的事情:

                    ctx.beginPath();
                        ctx.moveTo(lastX,lastY);
                        ctx.lineTo(x,y);
                        ctx.lineWidth = s*2;
                        ctx.stroke();
                    ctx.closePath();

现在,我需要的是有时能够将此路径存储在一个数组中。然后,我需要稍后能够返回并更改数组中所有路径的颜色。 (显然,我也不知道该怎么做。)

【问题讨论】:

  • 也许将这些操作保存在一个函数中?所以你会有一个函数数组。
  • 当您需要这种功能时,请考虑使用 SVG。

标签: javascript html canvas


【解决方案1】:

看起来现在可以使用新的path2D 对象。

新的 Path2D API(可从 Firefox 31+ 获得)允许您存储路径,从而简化您的画布绘图代码并使其运行更快。构造函数提供了三种创建 Path2D 对象的方法:

new Path2D();     // empty path object
new Path2D(path); // copy from another path
new Path2D(d);    // path from from SVG path data

采用 SVG 路径数据构建的第三个版本特别好用。您现在也可以重复使用 SVG 路径直接在画布上绘制相同的形状:

var p = new Path2D("M10 10 h 80 v 80 h -80 Z");

信息取自Mozilla official site

【讨论】:

    【解决方案2】:

    您可以将绘制路径所需的所有数据序列化到 javascript 对象中

    使用 javascript 对象的好处是,如果您需要将路径移动到不同的位置(例如回到服务器),可以进一步将对象序列化为 JSON。

    var path1={
        lineWidth:1, 
        stroke:"blue", 
        points:[{x:10,y:10},{x:100,y:50},{x:30,y:200}]
    };
    

    然后您可以使用该对象来绘制/重绘该路径

        function draw(path){
    
            // beginPath
            ctx.beginPath();
    
            // move to the beginning point of this path
            ctx.moveTo(path.points[0].x,path.points[0].y);
    
            // draw lines to each point on the path
            for(pt=1;pt<path.points.length;pt++){
                var point=path.points[pt];
                ctx.lineTo(point.x,point.y);
            }
    
            // set the path styles (color & linewidth)
            ctx.strokeStyle=path.stroke;
            ctx.lineWidth=path.lineWidth;
    
            // stroke this path
            ctx.stroke();
        }
    

    要改变路径的颜色,你只需要改变对象的 stroke 属性并再次调用 draw():

        paths[0].stroke="orange";
        paths[1].stroke="green";
        draw();
    

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

    <!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(){
    
        // get references to canvas and context
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        // serialize paths to a javascript objects
        var path1={lineWidth:1, stroke:"blue", points:[]};
        var path2={lineWidth:4, stroke:"red", points:[]};
    
        // save the paths to an array
        var paths=[];
        paths.push(path1);
        paths.push(path2);
    
    
        // build test path1
        newPoint(25,25,path1);
        newPoint(100,50,path1);
        newPoint(50,75,path1);
        newPoint(25,25,path1);
    
        // build test path2
        newPoint(200,100,path2);
        newPoint(250,100,path2);
        newPoint(250,200,path2);
        newPoint(200,200,path2);
        newPoint(200,100,path2);
    
        // draw the paths defined in the paths array
        draw();
    
        // add a new point to a path
        function newPoint(x,y,path){
            path.points.push({x:x,y:y});
        }
    
    
        function draw(){
    
            ctx.clearRect(0,0,canvas.width,canvas.height);
    
            for(p=0;p<paths.length;p++){
    
                // get a path definition
                var path=paths[p];
    
                // beginPath
                ctx.beginPath();
    
                // move to the beginning point of this path
                ctx.moveTo(path.points[0].x,path.points[0].y);
    
                // draw lines to each point on the path
                for(pt=1;pt<path.points.length;pt++){
                    var point=path.points[pt];
                    ctx.lineTo(point.x,point.y);
                }
    
                // set the path styles (color & linewidth)
                ctx.strokeStyle=path.stroke;
                ctx.lineWidth=path.lineWidth;
    
                // stroke this path
                ctx.stroke();
    
            }
    
        }
    
        // test
        // change the stroke color on each path
        $("#recolor").click(function(){
            paths[0].stroke="orange";
            paths[1].stroke="green";
            draw();
        });
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <button id="recolor">Recolor</button><br>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • 如果需要知道用户点击了哪个路径怎么办?为了改变颜色、形状、填充等等,甚至从画布中删除对象。
    【解决方案3】:

    在画布中,如果不清除它并重新绘制它,就无法更改画布视图;因此,您需要创建一个函数来绘制画布。 在数组中存储您的行位置,在函数循环期间通过数组并添加这些。 显然你可以随时重绘画布;通常你会设置一个事件监听器或计时事件

    【讨论】:

      【解决方案4】:

      简短的回答:你不能。它在 Canvas2D API 的下一个草案中(请参阅 http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/#path-objects),但尚不支持。

      更长的答案:你不能,但你可以编写一个表示路径的对象,并给它一个draw(canvas) 函数,以便它使用你选择的颜色和填充属性将自己绘制到画布上。例如:

      var Path = function() {
        this.instructions = [];
      }
      Path.prototype = {
        instructions: [],
        moveTo: function(x,y) {
          instructions.push({
            type: "moveTo",
            arguments: [x,y]
          });
        }
        ...
        draw: function(canvas) {
          var ctx = canvas.getContext("2d");
          ctx.beginPath();
          this.instructions.forEach(function(i) {
            ctx[i.type].apply(i.arguments);
          });
          ctx.closePath();
        } 
      } 
      

      【讨论】:

      • 请谨慎调用对象Path,因为这是为将来的路径保留的。
      • 相当。虽然目前还不清楚新规范何时会进入滚动发布。 (您始终可以使用if(window.Path) { ... },但不同的 varname 可能会更好。
      【解决方案5】:

      这可能会有所帮助:

      http://www.rgraph.net/blog/2015/september/svg-style-paths-for-canvas-with-the-rgraph-path-function.html

      这是一个允许您使用字符串的函数,该字符串由字母和数字组成,然后由该函数解释并执行操作。所以现在你的路径可以是一个字符串 - 就像 SVG 路径一样 - 它们更容易传递和/或存储在数据库中。

      因此,绘制矩形的路径可能如下所示:

      b r 5 5 100 100 f 红色

      这意味着:

      b: beginPath()
      r: rect()
      f: fill()
      

      【讨论】:

        猜你喜欢
        • 2011-12-09
        • 1970-01-01
        • 2014-02-13
        • 1970-01-01
        • 2012-03-16
        • 2018-05-10
        • 1970-01-01
        • 2011-08-29
        • 2018-11-01
        相关资源
        最近更新 更多