CyanPrime
CyanPrime

Reputation: 5193

How to draw polygons on an HTML5 canvas?

I need to know how to draw polygons on a canvas. Without using jQuery or anything like that.

Upvotes: 126

Views: 225772

Answers (12)

canvastag
canvastag

Reputation: 508

//poly [x,y, x,y, x,y.....];
var poly=[ 5,5, 100,50, 50,100, 10,90 ];
var canvas=document.getElementById("canvas")
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#f00';

ctx.beginPath();
ctx.moveTo(poly[0], poly[1]);

for(let item=2 ; item < poly.length-1 ; item+=2 ){
  ctx.lineTo( poly[item] , poly[item+1] )
}
 
ctx.closePath();
ctx.fill();

Upvotes: 42

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48751

Here is a function approach at three different ways to draw polygons.

  1. Origin, size and radius
  2. Points in a flat array [x1, y1, x2, y2, ..., xN, yN]
  3. Points in a point array { x: int, y: int }[]

Stroke is the default, but fill can also be called. These could either be moved outside the function, or boolean parameters can be added. Alternatively, there can be two methods fillPolygon or strokePolygon, but these are now limited in functionality.

const ctx = document.getElementById('drawing').getContext('2d');

const main = () => {
  ctx.strokeStyle = '#000';
  ctx.lineWidth = 1;

  drawPolygon(ctx, 25, 25, 20);      // Triangle (default)
  drawPolygon(ctx, 75, 25, 20, 6);   // Hexagon
  drawPolygon(ctx, 125, 25, 20, 20); // Icosahedron

  ctx.strokeStyle = '#070';
  ctx.fillStyle = '#ff0';
  ctx.lineWidth = 3;

  drawFreePolygon(ctx, [30, 80, 30, 100, 70, 100, 70, 80, 50, 60]);
  ctx.fill();
  drawFreePolygon2(ctx, [{ x: 90, y: 80 }, { x: 90, y: 100 }, { x: 130, y: 100 }, { x: 130, y: 80 }, { x: 110, y: 60 }]);
};

const drawPolygon = (ctx, x, y, radius, sides = 3) => {
  ctx.beginPath();
  ctx.moveTo(x + radius * Math.cos(0), y + radius * Math.sin(0));
  for (let i = 1; i <= sides; i += 1) {
    ctx.lineTo(x + radius * Math.cos(i * 2 * Math.PI / sides), y + radius * Math.sin(i * 2 * Math.PI / sides));
  }
  ctx.closePath();
  ctx.stroke(); // Could be called outside
};

const drawFreePolygon = (ctx, points) => {
  ctx.beginPath();
  ctx.moveTo(points[0], points[1]);
  for (let i = 2; i < points.length - 1; i += 2) {
    ctx.lineTo(points[i], points[i + 1]);
  }
  ctx.closePath();
  ctx.stroke(); // Could be called outside
};

const drawFreePolygon2 = (ctx, points) => {
  const [{ x: startX, y: startY }] = points;
  ctx.beginPath();
  ctx.moveTo(startX, startY);
  points.forEach(({ x, y }) => {
    ctx.lineTo(x, y);
  });
  ctx.closePath();
  ctx.stroke(); // Could be called outside
};

main();
#hexagon { border: thin dashed red; }
<canvas id="drawing"></canvas>

Related: https://stackoverflow.com/a/74694484/1762224

Upvotes: 1

var ctx = document.getElementById('hexagon').getContext('2d');

// hexagon
var numberOfSides = 4,
    size = 25,
    Xcenter = 40,
    Ycenter = 40;

ctx.beginPath();
ctx.moveTo (Xcenter +  size * Math.cos(0), Ycenter +  size *  Math.sin(0));          

for (var i = 1; i <= numberOfSides;i += 1) {
  ctx.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));
}

ctx.strokeStyle = "#000000";
ctx.lineWidth = 1;
ctx.stroke();
#hexagon { border: thin dashed red; }
<canvas id="hexagon"></canvas>

Upvotes: -1

Danielkenny
Danielkenny

Reputation: 1

Let's do that with HTML and get that down to this:

<!DOCTYPE html>
 <html>
 <head>
   <title> SVG hexagon </title>
 </head>

 <body>
   <svg width="300" height="110" >
     <polygon point="50 3, 100 28, 100 75, 50 100, 3 75, 3 25" stroke="red" fill="lime" stroke-width="5"/>
   </svg>
 </body>
</html>

Upvotes: 0

Andrew Staroscik
Andrew Staroscik

Reputation: 2704

from http://www.scienceprimer.com/drawing-regular-polygons-javascript-canvas:

The following code will draw a hexagon. Change the number of sides to create different regular polygons.

var ctx = document.getElementById('hexagon').getContext('2d');

// hexagon
var numberOfSides = 6,
    size = 20,
    Xcenter = 25,
    Ycenter = 25;

ctx.beginPath();
ctx.moveTo (Xcenter +  size * Math.cos(0), Ycenter +  size *  Math.sin(0));          

for (var i = 1; i <= numberOfSides;i += 1) {
  ctx.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));
}

ctx.strokeStyle = "#000000";
ctx.lineWidth = 1;
ctx.stroke();
#hexagon { border: thin dashed red; }
<canvas id="hexagon"></canvas>

Upvotes: 50

Azurethi
Azurethi

Reputation: 68

For the people looking for regular polygons:

function regPolyPath(r,p,ctx){ //Radius, #points, context
  //Azurethi was here!
  ctx.moveTo(r,0);
  for(i=0; i<p+1; i++){
    ctx.rotate(2*Math.PI/p);
    ctx.lineTo(r,0);
  }
  ctx.rotate(-2*Math.PI/p);
}

Use:

//Get canvas Context
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.translate(60,60);    //Moves the origin to what is currently 60,60
//ctx.rotate(Rotation);  //Use this if you want the whole polygon rotated
regPolyPath(40,6,ctx);   //Hexagon with radius 40
//ctx.rotate(-Rotation); //remember to 'un-rotate' (or save and restore)
ctx.stroke();

Upvotes: 1

phihag
phihag

Reputation: 288298

Create a path with moveTo and lineTo (live demo):

var ctx = canvas.getContext('2d');
ctx.fillStyle = '#f00';
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100,50);
ctx.lineTo(50, 100);
ctx.lineTo(0, 90);
ctx.closePath();
ctx.fill();

Upvotes: 206

Sabba Keynejad
Sabba Keynejad

Reputation: 8591

To make a simple hexagon without the need for a loop, Just use the beginPath() function. Make sure your canvas.getContext('2d') is the equal to ctx if not it will not work.

I also like to add a variable called times that I can use to scale the object if I need to.This what I don't need to change each number.

     // Times Variable 

     var times = 1;

    // Create a shape

    ctx.beginPath();
    ctx.moveTo(99*times, 0*times);
    ctx.lineTo(99*times, 0*times);
    ctx.lineTo(198*times, 50*times);
    ctx.lineTo(198*times, 148*times);
    ctx.lineTo(99*times, 198*times);
    ctx.lineTo(99*times, 198*times);
    ctx.lineTo(1*times, 148*times);
    ctx.lineTo(1*times,57*times);
    ctx.closePath();
    ctx.clip();
    ctx.stroke();

Upvotes: 0

Koen.
Koen.

Reputation: 27049

In addition to @canvastag, use a while loop with shift I think is more concise:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var poly = [5, 5, 100, 50, 50, 100, 10, 90];

// copy array
var shape = poly.slice(0);

ctx.fillStyle = '#f00'
ctx.beginPath();
ctx.moveTo(shape.shift(), shape.shift());
while(shape.length) {
  ctx.lineTo(shape.shift(), shape.shift());
}
ctx.closePath();
ctx.fill();

Upvotes: 3

John R
John R

Reputation: 126

Here is a function that even supports clockwise/anticlockwise drawing do that you control fills with the non-zero winding rule.

Here is a full article on how it works and more.

// Defines a path for any regular polygon with the specified number of sides and radius, 
// centered on the provide x and y coordinates.
// optional parameters: startAngle and anticlockwise

function polygon(ctx, x, y, radius, sides, startAngle, anticlockwise) {
  if (sides < 3) return;
  var a = (Math.PI * 2)/sides;
  a = anticlockwise?-a:a;
  ctx.save();
  ctx.translate(x,y);
  ctx.rotate(startAngle);
  ctx.moveTo(radius,0);
  for (var i = 1; i < sides; i++) {
    ctx.lineTo(radius*Math.cos(a*i),radius*Math.sin(a*i));
  }
  ctx.closePath();
  ctx.restore();
}

// Example using the function.
// Define a path in the shape of a pentagon and then fill and stroke it.
context.beginPath();
polygon(context,125,125,100,5,-Math.PI/2);
context.fillStyle="rgba(227,11,93,0.75)";
context.fill();
context.stroke();

Upvotes: 5

Jignesh Variya
Jignesh Variya

Reputation: 1919

//create and fill polygon
CanvasRenderingContext2D.prototype.fillPolygon = function (pointsArray, fillColor,     strokeColor) {
    if (pointsArray.length <= 0) return;
    this.moveTo(pointsArray[0][0], pointsArray[0][1]);
    for (var i = 0; i < pointsArray.length; i++) {
        this.lineTo(pointsArray[i][0], pointsArray[i][1]);
    }
    if (strokeColor != null && strokeColor != undefined)
        this.strokeStyle = strokeColor;

    if (fillColor != null && fillColor != undefined) {
        this.fillStyle = fillColor;
        this.fill();
    }
}
//And you can use this method as 
var polygonPoints = [[10,100],[20,75],[50,100],[100,100],[10,100]];
context.fillPolygon(polygonPoints, '#F00','#000');

Upvotes: 10

ankur
ankur

Reputation: 21

You can use the lineTo() method same as: var objctx = canvas.getContext('2d');

        objctx.beginPath();
        objctx.moveTo(75, 50);
        objctx.lineTo(175, 50);
        objctx.lineTo(200, 75);
        objctx.lineTo(175, 100);
        objctx.lineTo(75, 100);
        objctx.lineTo(50, 75);
        objctx.closePath();
        objctx.fillStyle = "rgb(200,0,0)";
        objctx.fill();

if you not want to fill the polygon use the stroke() method in the place of fill()

You can also check the following: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

thanks

Upvotes: 2

Related Questions