¿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.

CyanPrime
fuente
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();
Phihag
fuente
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();
etiqueta de lienzo
fuente
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>

Andrew Staroscik
fuente
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');
Jignesh Variya
fuente
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();
John R
fuente
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

ankur
fuente
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();
Koen.
fuente
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();
Sabba Keynejad
fuente
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();
Azurethi
fuente