ChatGPT解决这个技术问题 Extra ChatGPT

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.

It's good to remember that whatever can be done without a third-party library, should usually be done so.

p
phihag

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

@Gio Borje: AFAIK, jsFiddle doesn't care about canvas, that's your browser. jsFiddle just feeds your HTML/CSS/JS back to you.
Excellent solution. Very neat code. thank u @phihag. Something that I can understand!
can you replace c2 with ctx? I think it's more common use for canvas context. great answer by the way
@user1893354 Thank you very much for the notice. Indeed, there seems to be a problem with jsfiddle there - the error message is completely unrelated to the canvas. Replaced with a very simple live demo site.
M
Mr. Polywhirl

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


This was great, very elegant, also, if you add: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); You can fill the shape.
this is great - i've been sitting playing with it, but cannot work out how i would get the chosen polygon to rotate - any ideas?
There are a few ways to get what you want. One option is to use the built in cxt.rotate() method [along with cxt.save() and cxt.restore()] to rotate parts of the canvas. Alternatively, adding a consistent value to the cos and sin functions will also work. See this jsfiddle for a demonstration: jsfiddle.net/kwyhn3ba
thanks for that - i came across the same solution after reading through the logic on the science primer link you provided. var angle = i * 2 * Math.PI / shape.currentSides + rotation added to the cos and sin values worked for me... thanks again
If (as in my case) you just want the starting point to be the middle top of the polygon rather than the middle right, flip the sin and cos calls and change Ycenter + to Ycenter - on both places (leaving it as a sum rather than a difference of the values results in it starting with a point at the bottom of the resultant shape). I am not a clever man when it comes to trig, so take with a grain of salt; but this achieved what I wanted at least.
D
Dave Sumter
//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();

This is why I wish I could fundamentally understand the JavaScript vanilla for method. That one line of code simplified things so much. I typically use the jQuery .each() but it's application is much less versatile.
@AlexanderDixon The javascript above is really not a good example. All variables need var, in the above code item is a polluting the global namespace. Everything is on one line, which reduces readability. If you don't care about readability then you might as well remove the curly brackets.
@canvastag Nice work dynamic job. This answer is better from accepted answer for me. I don't understand "Query .each()" ... this is some magic function who does take memory. Also for global namespace ;) funny this is just example make it like class if you want that.
J
Jignesh Variya
//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');

Interesting... Actually does a moveTo AND a lineTo for the first point... but now that I think about it... who cares?
J
John R

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

That article is rather long to say "your drawing a circle with less edges". You might want to cache the results to avoid calling cos and sin so much (forgive me if its doing it already, I'm not a JavaScript programmer).
K
Koen.

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

a
ankur

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


A
Azurethi

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

S
Sabba Keynejad

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

D
Danielkenny

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>

P
PEDDINTI VISHNU CHAKRADHAR RED

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