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

Posted

技术标签:

【中文标题】如何在 HTML5 画布上绘制多边形?【英文标题】:How to draw polygons on an HTML5 canvas? 【发布时间】:2011-06-17 22:06:12 【问题描述】:

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

【问题讨论】:

请记住,任何可以在没有第三方库的情况下完成的事情,通常都应该这样做。 【参考方案1】:

使用moveTolineTo (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 不关心画布,那是你的浏览器。 jsFiddle 只是将您的 html/CSS/JS 反馈给您。 优秀的解决方案。非常整洁的代码。谢谢你@phihag。我能理解的东西! 可以把c2换成ctx吗?我认为画布上下文更常见。顺便说一句,答案很好 @user1893354 非常感谢您的通知。确实,那里的 jsfiddle 似乎存在问题 - 错误消息与画布完全无关。替换为一个非常简单的现场演示站点。【参考方案2】:

来自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; 
&lt;canvas id="hexagon"&gt;&lt;/canvas&gt;

【讨论】:

这很棒,也很优雅,如果你添加:cxt.save();cxt.fillStyle = "#FF000";cxt.fill();cxt.restore();你可以填充形状。 这很棒 - 我一直在玩它,但不知道如何让选定的多边形旋转 - 有什么想法吗? 有几种方法可以得到你想要的。一种选择是使用内置的 cxt.rotate() 方法 [连同 cxt.save() 和 cxt.restore()] 来旋转部分画布。或者,为 cos 和 sin 函数添加一致的值也可以。请参阅此 jsfiddle 进行演示:jsfiddle.net/kwyhn3ba 感谢您 - 在阅读了您提供的科学入门链接上的逻辑后,我遇到了相同的解决方案。 var angle = i * 2 * Math.PI / shape.currentSides + rotation 添加到对我有用的 cos 和 sin 值...再次感谢 如果(在我的例子中)你只是希望起点是多边形的中间顶部而不是中间右侧,翻转 sincos 调用并更改 Ycenter +Ycenter - 在两个地方(将其保留为总和而不是值的差会导致它从结果形状底部的一个点开始)。在触发方面,我不是一个聪明的人,所以请持保留态度;但这至少实现了我想要的。【参考方案3】:
//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(),但它的应用程序不太通用。 @AlexanderDixon 上面的 javascript 真的不是一个很好的例子。 所有变量都需要var,在上面的代码中item是一个污染全局命名空间。一切都在一条线上,这降低了可读性。如果您不关心可读性,那么您不妨删除大括号。 @canvastag 干得好动态工作。这个答案比我接受的答案更好。我不明白“Query .each()”……这是一些占用记忆的神奇功能。也适用于全局命名空间;)有趣的是,如果你愿意,这只是一个例子,让它像类一样。【参考方案4】:
//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...但是现在我想起来了...谁在乎呢?【参考方案5】:

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

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

【讨论】:

那篇文章很长,说“你画了一个边少的圆”。您可能希望缓存结果以避免调用 cos 和 sin (如果它已经这样做了,请原谅我,我不是 JavaScript 程序员)。【参考方案6】:

除了@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();

【讨论】:

【参考方案7】:

您可以使用与以下相同的 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/

谢谢

【讨论】:

【参考方案8】:

要制作一个不需要循环的简单六边形,只需使用 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();

【讨论】:

【参考方案9】:

对于寻找正多边形的人:

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

【讨论】:

【参考方案10】:

让我们用 HTML 来做这件事,并把它归结为:

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

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

【讨论】:

【参考方案11】:

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; 
&lt;canvas id="hexagon"&gt;&lt;/canvas&gt;

【讨论】:

以上是关于如何在 HTML5 画布上绘制多边形?的主要内容,如果未能解决你的问题,请参考以下文章

从坐标图中绘制多边形画布

我们如何在 html5 画布上绘制调整大小的图像?

HTML5 Canvas - 如何在画布中的图像上绘制矩形

如何在 HTML5 画布上逐个像素地绘制

如何使用html5画布元素绘制透明图像

使用 html5 画布将图像剪辑成多边形的可重用函数