如何在HTML5画布上绘制多边形?


94

我需要知道如何在画布上绘制多边形。不使用jQuery或类似的东西。


10
最好记住,没有第三方库就可以完成任何操作,通常都应该这样做。
罗德里戈

Answers:


164

使用moveTo和创建一个路径lineTo实时演示):

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

100
@Gio Borje:AFAIK,jsFiddle不在乎画布,那是您的浏览器。jsFiddle只是将您的HTML / CSS / JS反馈给您。
亩太短了,

2
优秀的解决方案。非常简洁的代码。谢谢你@phihag 我能理解的东西!
bytise

1
可以用ctx替换c2吗?我认为它在画布上下文中更常见。好的答案
-gididaf

@ user1893354非常感谢您的通知。确实,那里的jsfiddle似乎有问题-错误消息与画布完全无关。替换为一个非常简单的实时演示站点。
phihag

34
//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( item=2 ; item < poly.length-1 ; item+=2 ){ctx.lineTo( poly[item] , poly[item+1] )}

ctx.closePath();
ctx.fill();

这就是为什么我希望我可以从根本上理解JavaScript vanilla for方法。一行代码简化了很多事情。我通常使用jQuery,.each()但是它的应用程序的通用性要差得多。
亚历山大·迪克森

7
@AlexanderDixon上面的javascript确实不是一个好例子。上面的代码中所有需要的变量都是对全局名称空间的污染。一切都在一行上,这降低了可读性。如果您不关心可读性,那么不妨删除大括号。varitem
AnnanFay

@canvastag不错的工作动态工作。这个答案比我接受的答案更好。我不懂“ Query .each()” ...这是一些魔术函数,确实占用内存。同样对于全局名称空间;)有趣的是,这只是示例,如果需要,可以使其像类。
尼古拉·卢基奇

33

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

以下代码将绘制一个六边形。更改边数以创建不同的规则多边形。

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>


3
如果添加的话,这很棒,也很优雅: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); 您可以填充形状。
samuelkobe 2014年

太好了-我一直坐在那里玩,但是无法弄清楚如何旋转选定的多边形-有什么想法吗?
eskimomatt 2015年

1
有几种方法可以获取您想要的东西。一种选择是使用内置的cxt.rotate()方法[以及cxt.save()和cxt.restore())来旋转画布的某些部分。或者,也可以在cos和sin函数中添加一致的值。观看此jsfiddle进行演示:jsfiddle.net/kwyhn3ba
Andrew Staroscik 2015年

谢谢您-阅读完您提供的科学入门链接中的逻辑后,我遇到了相同的解决方案。var angle = i * 2 * Math.PI / shape.currentSides + rotation增加到cos和sin值对我
有用

如果(例如,在我的情况下)您只是希望起点是多边形的中间顶部而不是中间的中间位置,则翻转sincos调用并更改Ycenter +Ycenter -两个位置(将其作为总和而不是值的差)会导致它从最终形状底部的一个点开始)。我不是一个聪明的人,所以要带些盐。但这至少达到了我想要的。
约瑟夫·马里克

9
//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');

有趣的是……实际上,moveTo和lineTo确实是第一点……但是现在我考虑了……谁在乎?
詹姆斯·牛顿,

3

这是一个甚至支持顺时针/逆时针绘制的函数,您可以使用非零缠绕规则来控制填充。

这是有关其工作原理的完整文章,以及更多。

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

那篇文章说“您用更少的边缘绘制一个圆”很长。您可能希望缓存结果以避免过多调用cos和sin(如果已经这样做,请原谅我,我不是JavaScript程序员)。
QuantumKarl 2015年

1

您可以使用与以下相同的lineTo()方法: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();

如果您不想填充多边形,请使用stroke()方法代替fill()

您还可以检查以下内容:http : //www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

谢谢


1

除了@canvastag之外,我认为使用while循环shift更简洁:

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

0

要制作不需要循环的简单六边形,只需使用beginPath()函数。确保您的canvas.getContext('2d')等于ctx,否则将不起作用。

我还喜欢添加一个名为times的变量,如果需要的话可以用来缩放对象,这不需要更改每个数字。

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

0

对于寻找正多边形的人:

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

用:

//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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.