Nick Dangerous
Nick Dangerous

Reputation: 31

How do I draw a shape and then declare it a variable?

<!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

Answers (2)

Blindman67
Blindman67

Reputation: 54099

You could use 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); 

Example

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

Priyank Trivedi
Priyank Trivedi

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

Related Questions