HTML5 Canvas: Manipulating Individual Paths

How can I save a specific path to a javascript variable/array, and later manipulate it, when using an HTML5 canvas? Here's what I'm doing thus far:

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

Now, what I need is to be able to, at times, store this path in an array. Then, I need to be able to go back and change the color of all the paths in the array later. (I don't know how to do this either, obviously.)

Answers:

Answer

You can serialize all the data needed to draw a path into a javascript object

The benefit of using javascript objects is that you can further serialize the object to JSON if you need to move your paths to a different location (like back to a server).

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

Then you can use that object to draw/redraw that path

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

To change the colors of the paths, you just have to change the stroke property of the object and call draw() again:

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

Here is code and a Fiddle: 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>
Answer

It looks like it is now possible with a new path2D object.

The new Path2D API (available from Firefox 31+) lets you store paths, which simplifies your canvas drawing code and makes it run faster. The constructor provides three ways to create a Path2D object:

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

The third version, which takes SVG path data to construct, is especially handy. You can now re-use your SVG paths to draw the same shapes directly on a canvas as well:

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

Information is taken from Mozilla official site.

Answer

In canvas you cannot change the canvas view without clearing it and redrawing it; therefore you need to create a function to draw the canvas. In the array store your line Positions, the during the function loop through the array and add these. Obviously you can redraw the canvas at any time; usually you will set up an event listener or timing event

Answer

Short answer: you can't. It's in the next draft for the Canvas2D API (see http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/#path-objects), but is not supported yet.

Longer answer: you can't, but you can write an object that represents a path, and give it a draw(canvas) function so that it draws itself onto a canvas with your chosen colors and fill properties. For instance:

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

This might help:

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

It's a function that allows you to use a string, that consists of letters and numbers which are then interpreted by this function and the actions carried out. So now your path can be a string - just like SVG paths - and they're far easier to pass around and/or store in a database.

So a path to draw a rectangle might look like this:

b r 5 5 100 100 f red

That means:

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

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.