Come disegnare poligoni su una tela HTML5?


95

Ho bisogno di sapere come disegnare poligoni su una tela. Senza usare jQuery o qualcosa del genere.


10
È bene ricordare che tutto ciò che può essere fatto senza una libreria di terze parti, di solito dovrebbe essere fatto così.
Rodrigo

Risposte:


165

Crea un percorso con moveToe lineTo( demo live ):

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 non si preoccupa della tela, questo è il tuo browser. jsFiddle ti restituisce solo il tuo HTML / CSS / JS.
mu è troppo breve il

2
Ottima soluzione. Codice molto accurato. grazie @phihag. Qualcosa che posso capire!
bytise

1
puoi sostituire c2 con ctx? Penso che sia più comune per il contesto canvas. ottima risposta a proposito
gididaf

@ user1893354 Grazie mille per l'avviso. In effetti, sembra che ci sia un problema con jsfiddle lì: il messaggio di errore è completamente estraneo alla tela. Sostituito con un sito demo live molto semplice.
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();

Questo è il motivo per cui vorrei poter capire fondamentalmente il formetodo vanilla di JavaScript . Quella riga di codice ha semplificato così tanto le cose. Di solito uso jQuery .each()ma la sua applicazione è molto meno versatile.
Alexander Dixon

7
@AlexanderDixon Il javascript sopra non è davvero un buon esempio. Tutte le variabili hanno bisogno var, nel codice sopra itemè un inquinamento dello spazio dei nomi globale. Tutto è su una riga, il che riduce la leggibilità. Se non ti interessa la leggibilità, potresti anche rimuovere le parentesi graffe.
AnnanFay

@canvastag Bel lavoro lavoro dinamico. Questa risposta è migliore da una risposta accettata per me. Non capisco "Query .each ()" ... questa è una funzione magica che prende la memoria. Anche per lo spazio dei nomi globale;) divertente questo è solo un esempio rendilo come una classe se lo desideri.
Nikola Lukic

34

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

Il codice seguente disegnerà un esagono. Modificare il numero di lati per creare diversi poligoni regolari.

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
Questo è stato fantastico, anche molto elegante, se aggiungi: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); puoi riempire la forma.
samuelkobe

questo è fantastico - ci stavo giocando, ma non riesco a capire come farei ruotare il poligono scelto - qualche idea?
eskimomatt

1
Ci sono alcuni modi per ottenere ciò che desideri. Un'opzione è usare il metodo cxt.rotate () incorporato [insieme a cxt.save () e cxt.restore ()] per ruotare parti dell'area di disegno. In alternativa, funzionerà anche l'aggiunta di un valore coerente alle funzioni cos e sin. Guarda questo jsfiddle per una dimostrazione: jsfiddle.net/kwyhn3ba
Andrew Staroscik

grazie per questo - mi sono imbattuto nella stessa soluzione dopo aver letto la logica sul link del primer scientifico che hai fornito. var angle = i * 2 * Math.PI / shape.currentSides + rotationaggiunto ai valori cos e sin ha funzionato per me ... grazie ancora
eskimomatt

Se (come nel mio caso) vuoi solo che il punto di partenza sia il centro in alto del poligono piuttosto che il centro a destra, capovolgi sine coschiama e cambia Ycenter +in Ycenter -su entrambi i punti (lasciandolo come una somma piuttosto che come una differenza dei valori risulta in esso che inizia con un punto nella parte inferiore della forma risultante). Non sono un uomo intelligente quando si tratta di trigonometria, quindi prenditela con le pinze; ma questo ha ottenuto almeno quello che volevo.
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');

Interessante ... In realtà fa una mossa A E una linea A per il primo punto ... ma ora che ci penso ... chi se ne frega?
James Newton

3

Ecco una funzione che supporta anche il disegno in senso orario / antiorario che controlli i riempimenti con la regola di avvolgimento diverso da zero.

Ecco un articolo completo su come funziona e altro ancora.

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

L'articolo è piuttosto lungo per dire "stai disegnando un cerchio con meno bordi". Potresti voler memorizzare nella cache i risultati per evitare di chiamare cos e sin così tanto (perdonami se lo sta già facendo, non sono un programmatore JavaScript).
QuantumKarl

1

Puoi utilizzare il metodo lineTo () come: 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();

se non vuoi riempire il poligono usa il metodo stroke () al posto di fill ()

Puoi anche controllare quanto segue: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Grazie


1

Oltre a @canvastag, usa un whileciclo con shiftpenso sia più 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

Per creare un semplice esagono senza la necessità di un ciclo, usa la funzione beginPath (). Assicurati che il tuo canvas.getContext ('2d') sia uguale a ctx altrimenti non funzionerà.

Mi piace anche aggiungere una variabile chiamata volte che posso usare per ridimensionare l'oggetto se necessario, questo non è necessario per cambiare ogni numero.

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

Per le persone che cercano poligoni regolari:

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

Uso:

//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();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.