Reputation: 31
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="350" height="300"
style="border:6px solid black;">
</canvas>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = 'gold';
ctx.strokeRect(20, 10, 160, 100);
</script>
</body>
</html>
Now, I want to go ahead and turn this drawn rectangle:
ctx.strokeStyle = 'gold';
ctx.strokeRect(20, 10, 160, 100);
Into a variable that I can just simply name "Rectangle" I can easily modify and call it out throughout my project. How can I do that? thank you!
Upvotes: 0
Views: 836
Reputation: 54099
Path2D
Using Path2D
to create paths and render them as needed is convenient and from a rendering standpoint paths are a little quicker as the sub paths do not need to be created every time you render the path.
It is best to create the sub paths around the origin (0,0) so you can easily move, rotate and scale them as needed.
Example creating some paths with different content
function createRect() {
const path = new Path2D();
path.rect(-70, -45, 140, 90); // add the sub path;
return path;
}
function createCircle() {
const path = new Path2D();
path.arc(0, 0, 50, 0, Math.PI * 2); // add the sub path;
return path;
}
function createRandLines() {
const path = new Path2D();
var i = 10;
while(i--) {
path.moveTo(Math.random() * 20 - 10, Math.random() * 20 - 10);
path.lineTo(Math.random() * 20 - 10, Math.random() * 20 - 10);
}
return path;
}
To create the paths
const myCircle = createCircle();
const myRect = createCircle();
const myLines1 = createRandLines();
const myLines2 = createRandLines();
You can then render any of the paths with a single function.
function strokePath(path, x, y, lineWidth = ctx.lineWidth, color = ctx.strokeStyle) { // defaults to current style
ctx.setTransform(1, 0, 0, 1, x, y); // position the path so its (0,0) origin is at x,y
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke(path);
}
Passing the path position style and line width to draw the path.
const W = ctx.canvas.width;
const H = ctx.canvas.height;
strokePath(myCircle, Math.random() * W, Math.random() * H);
strokePath(myRect, Math.random() * W, Math.random() * H);
strokePath(myLines1, Math.random() * W, Math.random() * H);
strokePath(myLines2, Math.random() * W, Math.random() * H);
A more detailed draw function and some organisation in regards to the create path functions.
The example creates 4 paths once and then draws them many times, randomly positioned, rotated, scaled, alpha faded, colored, and filled.
const W = canvas.width;
const H = canvas.height;
const ctx = canvas.getContext("2d");
ctx.lineCap = ctx.lineJoin = "round";
// Some math utils
Math.TAU = Math.PI * 2;
Math.rand = (m = 0, M = 1) => Math.random() * (M - m) + m;
Math.randItem = array => array[Math.random() * array.length | 0];
const FACE = [[-3,-38,-34,-32,-47,-16,-48,15,-36,34,-5,43,32,38,47,12,47,-21,25,-35],[-31,-19,-42,-6,-32,1,-9,-6,-6,-24],[5,-24,3,-6,29,2,40,-5,33,-19],[-30,15,-14,32,12,31,29,15,15,15,-2,23,-17,16],[-28,-14,-29,-6,-18,-9,-17,-15],[11,-17,12,-8,20,-6,22,-13,18,-16],[2,-39,0,-53,-9,-60],[-14,17,-16,26,-7,28,-5,22],[2,21,1,28,11,27,13,16]];
// Object to hold path types
const paths = {
rect() {
const path = new Path2D();
path.rect(-20, -10, 40, 20); // add the sub path;
return path;
},
ellipse() {
const path = new Path2D();
path.ellipse(0, 0, 20, 10, 0, 0, Math.TAU); // add the sub path;
return path;
},
randLines() {
const path = new Path2D();
var i = 10;
while (i--) {
path.moveTo(Math.rand(-20, 20), Math.rand(-20, 20));
path.lineTo(Math.rand(-20, 20), Math.rand(-20, 20));
}
return path;
},
face() {
const path = new Path2D();
FACE .forEach(sub => { // each sub path
let i = 0;
path.moveTo(sub[i++] / 3, sub[i++] / 3);
while (i < sub.length) { path.lineTo(sub[i++] / 3, sub[i++] / 3) }
path.closePath();
});
return path;
}
};
// Function to draw scaled, rotated, faded, linewidth, colored path
function strokePath(path, x, y, scale, rotate, alpha, lineWidth, color, fillColor) {
ctx.lineWidth = lineWidth * (1 / scale); //Scale line width by inverse scale to ensure the pixel size is constant
ctx.setTransform(scale, 0, 0, scale, x, y); // position the path so its (0,0) origin is at x,y
ctx.rotate(rotate);
if (fillColor) {
ctx.globalAlpha = 1;
ctx.fillStyle = fillColor;
ctx.fill(path, "evenodd");
}
ctx.globalAlpha = alpha;
ctx.strokeStyle = color;
ctx.stroke(path);
}
// create some paths and colors
const pathArray = [paths.ellipse(), paths.rect(), paths.randLines(), paths.face()];
const colors = "#F00,#FA0,#0B0,#0AF,#00F,#F0A,#000,#888".split(",");
drawRandomPath();
function drawRandomPath() {
strokePath(
Math.randItem(pathArray), // random path
Math.rand(0, W), Math.rand(0, H), // random pos
Math.rand(0.25, 1), // random scale
Math.rand(0, Math.TAU), // random rotate
Math.rand(0.5, 1), // random alpha
1, // constant lineWidth
Math.randItem(colors), // random color
Math.rand() < 0.2 ? "#EED" : undefined, // Fill 1 in 5 with white
);
setTimeout(drawRandomPath, 250); // draw another path every quarter second.
}
* {margin:0px}
canvas {border:1px solid}
<canvas id="canvas" width="600" height="190"></canvas>
Upvotes: 1
Reputation: 276
You can not do that with current standards unfortunately, you will have to redraw the shape, you can do something like:
var shape = x:10,y:20,width:20,height:40
clear the canvas and redraw with created variable:
shape.width = 100;
ctx.rect(shape.x,shape.y,shape.width,shape.height);
Upvotes: 0