¿Cómo dibujar polígonos en un lienzo HTML5?


95

Necesito saber cómo dibujar polígonos en un lienzo. Sin usar jQuery ni nada de eso.


10
Es bueno recordar que todo lo que se pueda hacer sin una biblioteca de terceros, normalmente debería hacerse así.
Rodrigo

Respuestas:


165

Cree una ruta con moveToy lineTo( demostración en vivo ):

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 no se preocupa por el lienzo, ese es tu navegador. jsFiddle simplemente le devuelve su HTML / CSS / JS.
mu es demasiado corto

2
Excelente solucion. Código muy limpio. gracias @phihag. ¡Algo que puedo entender!
bytise

1
¿Puedes reemplazar c2 con ctx? Creo que es un uso más común para el contexto de lienzo. gran respuesta por cierto
gididaf

@ user1893354 Muchas gracias por el aviso. De hecho, parece haber un problema con jsfiddle allí: el mensaje de error no tiene ninguna relación con el lienzo. Reemplazado con un sitio de demostración en vivo muy simple.
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();

Es por eso que me gustaría poder entender fundamentalmente el formétodo vanilla de JavaScript . Esa línea de código simplificó mucho las cosas. Normalmente uso jQuery .each()pero su aplicación es mucho menos versátil.
Alexander Dixon

7
@AlexanderDixon El javascript anterior no es realmente un buen ejemplo. Todas las variables necesitan var, en el código anterior itemhay una contaminación del espacio de nombres global. Todo está en una línea, lo que reduce la legibilidad. Si no le importa la legibilidad, también puede eliminar las llaves.
AnnanFay

@canvastag Buen trabajo, trabajo dinámico. Esta respuesta es mejor de la respuesta aceptada para mí. No entiendo "Query .each ()" ... esta es una función mágica que toma memoria. También para el espacio de nombres global;) gracioso, esto es solo un ejemplo, hazlo como clase si quieres eso.
Nikola Lukic

34

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

El siguiente código dibujará un hexágono. Cambia el número de lados para crear diferentes polígonos regulares.

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
Esto fue genial, muy elegante, también, si agrega: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Puede rellenar la forma.
samuelkobe

esto es genial, he estado jugando con él, pero no puedo entender cómo haría que el polígono elegido gire, ¿alguna idea?
eskimomatt

1
Hay varias formas de conseguir lo que desea. Una opción es usar el método cxt.rotate () integrado [junto con cxt.save () y cxt.restore ()] para rotar partes del lienzo. Alternativamente, también funcionará agregar un valor consistente a las funciones cos y sin. Vea este jsfiddle para una demostración: jsfiddle.net/kwyhn3ba
Andrew Staroscik

gracias por eso, encontré la misma solución después de leer la lógica en el enlace del manual científico que proporcionó. var angle = i * 2 * Math.PI / shape.currentSides + rotationagregado a los valores de cos y pecado funcionó para mí ... gracias de nuevo
eskimomatt

Si (como en mi caso) lo que desea es el punto de partida a la parte superior central del polígono en lugar de la parte central derecha, voltear los siny coslas llamadas y el cambio Ycenter +a Ycenter -en ambos lugares (dejándola como una suma más que una diferencia de los valores da como resultado que comience con un punto en la parte inferior de la forma resultante). No soy un hombre inteligente cuando se trata de trigonometría, así que tómelo con un grano de sal; pero esto logró al menos lo que quería.
Joseph Marikle

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

Interesante ... En realidad, hace un moveTo Y una líneaTo para el primer punto ... pero ahora que lo pienso ... ¿a quién le importa?
James Newton

3

Aquí hay una función que incluso admite el dibujo en sentido horario / antihorario que controla los rellenos con la regla de bobinado distinto de cero.

Aquí hay un artículo completo sobre cómo funciona y más.

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

Ese artículo es bastante largo para decir "estás dibujando un círculo con menos bordes". Es posible que desee almacenar en caché los resultados para evitar llamar a cos y pecar tanto (perdóneme si ya lo está haciendo, no soy un programador de JavaScript).
QuantumKarl

1

Puede utilizar el método lineTo () igual que: 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();

si no desea llenar el polígono, use el método stroke () en lugar de fill ()

También puede comprobar lo siguiente: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Gracias


1

Además de @canvastag, use un whilebucle con shiftcreo que es más conciso:

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

Para hacer un hexágono simple sin la necesidad de un bucle, simplemente use la función beginPath (). Asegúrese de que su canvas.getContext ('2d') sea ​​igual a ctx si no, no funcionará.

También me gusta agregar una variable llamada tiempos que puedo usar para escalar el objeto si lo necesito. Esto es lo que no necesito para cambiar cada número.

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

Para las personas que buscan polígonos regulares:

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

Utilizar:

//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();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.