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.)
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.)
Share Improve this question edited Jan 21, 2016 at 21:30 Salvador Dali 223k151 gold badges724 silver badges765 bronze badges asked Oct 19, 2013 at 21:29 J SJ S 3,4965 gold badges22 silver badges28 bronze badges 2- 1 Maybe save those actions in a function? So you'll have an array of functions. – XCS Commented Oct 19, 2013 at 21:34
- Whenever you need this kind of functionality, consider using SVG. – slebetman Commented Oct 19, 2013 at 23:17
5 Answers
Reset to default 5You 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>
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.
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()
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
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();
}
}