Wie zeichne ich Polygone auf einer HTML5-Leinwand?

94

Ich muss wissen, wie man Polygone auf eine Leinwand zeichnet. Ohne jQuery oder ähnliches zu verwenden.

CyanPrime
quelle
10
Es ist gut daran zu denken, dass alles, was ohne eine Bibliothek eines Drittanbieters möglich ist, normalerweise so gemacht werden sollte.
Rodrigo

Antworten:

164

Erstellen Sie einen Pfad mit moveTound lineTo( 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();
Phihag
quelle
100
@Gio Borje: AFAIK, jsFiddle kümmert sich nicht um Leinwand, das ist dein Browser. jsFiddle gibt Ihnen nur Ihr HTML / CSS / JS zurück.
Mu ist zu kurz
2
Hervorragende Lösung. Sehr ordentlicher Code. danke dir @phihag. Etwas, das ich verstehen kann!
Bytise
1
Kannst du c2 durch ctx ersetzen? Ich denke, es wird häufiger für den Canvas-Kontext verwendet. tolle Antwort übrigens
Gididaf
@ user1893354 Vielen Dank für den Hinweis. In der Tat scheint es dort ein Problem mit jsfiddle zu geben - die Fehlermeldung hat nichts mit der Leinwand zu tun. Ersetzt durch eine sehr einfache Live-Demo-Site.
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();
canvastag
quelle
Aus diesem Grund wünschte ich mir, ich könnte die JavaScript-Vanille- forMethode grundlegend verstehen . Diese eine Codezeile hat die Dinge so sehr vereinfacht. Normalerweise verwende ich jQuery, .each()aber die Anwendung ist viel weniger vielseitig.
Alexander Dixon
7
@AlexanderDixon Das obige Javascript ist wirklich kein gutes Beispiel. Alle Variablen benötigen var, im obigen Code itemwird der globale Namespace verschmutzt. Alles ist in einer Zeile, was die Lesbarkeit verringert. Wenn Sie sich nicht um die Lesbarkeit kümmern, können Sie auch die geschweiften Klammern entfernen.
AnnanFay
@canvastag Gute Arbeit dynamischer Job. Diese Antwort ist besser von der akzeptierten Antwort für mich. Ich verstehe "Query .each ()" nicht ... dies ist eine magische Funktion, die Speicher benötigt. Auch für den globalen Namespace;) lustig ist dies nur ein Beispiel, mach es wie eine Klasse, wenn du das willst.
Nikola Lukic
33

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

Der folgende Code zeichnet ein Sechseck. Ändern Sie die Anzahl der Seiten, um verschiedene reguläre Polygone zu erstellen.

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
quelle
3
Das war großartig, auch sehr elegant, wenn Sie hinzufügen: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Sie können die Form füllen.
Samuelkobe
Das ist großartig - ich habe damit gesessen und gespielt, kann aber nicht herausfinden, wie ich das ausgewählte Polygon zum Drehen bringen würde - irgendwelche Ideen?
Eskimomatt
1
Es gibt verschiedene Möglichkeiten, um das zu bekommen, was Sie wollen. Eine Möglichkeit besteht darin, die integrierte Methode cxt.rotate () [zusammen mit cxt.save () und cxt.restore ()] zu verwenden, um Teile der Zeichenfläche zu drehen. Alternativ funktioniert auch das Hinzufügen eines konsistenten Werts zu den Funktionen cos und sin. Sehen Sie diese jsfiddle für eine Demonstration: jsfiddle.net/kwyhn3ba
Andrew Staroscik
Vielen Dank dafür - ich bin auf die gleiche Lösung gestoßen, nachdem ich die Logik des von Ihnen bereitgestellten Science-Primer-Links gelesen hatte. var angle = i * 2 * Math.PI / shape.currentSides + rotationzu den cos und sin Werten hinzugefügt hat für mich gearbeitet ... nochmals
vielen
Wenn Sie (wie in meinem Fall) möchten, dass der Startpunkt eher die mittlere Oberseite des Polygons als die mittlere rechte ist, drehen Sie das sinund cosruft auf und wechseln Sie Ycenter +zu Ycenter -beiden Stellen (wobei Sie es als Summe und nicht als Differenz der Werte belassen) führt dazu, dass es mit einem Punkt am unteren Rand der resultierenden Form beginnt). Ich bin kein kluger Mann, wenn es um Trigger geht, also nimm ein Körnchen Salz; aber das hat erreicht, was ich zumindest wollte.
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
quelle
Interessant ... Eigentlich macht ein MoveTo AND eine LineTo für den ersten Punkt ... aber jetzt, wo ich darüber nachdenke ... wen interessiert das?
James Newton
3

Hier ist eine Funktion, die sogar das Zeichnen im Uhrzeigersinn / gegen den Uhrzeigersinn unterstützt. Sie steuern Füllungen mit der Wicklungsregel ungleich Null.

Hier ist ein vollständiger Artikel darüber, wie es funktioniert und mehr.

// 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.
quelle
Dieser Artikel ist ziemlich lang zu sagen "Sie zeichnen einen Kreis mit weniger Kanten". Vielleicht möchten Sie die Ergebnisse zwischenspeichern, um zu vermeiden, dass cos und sin so oft aufgerufen werden (verzeihen Sie mir, wenn dies bereits geschieht, bin ich kein JavaScript-Programmierer).
QuantumKarl
1

Sie können die lineTo () -Methode wie folgt verwenden: 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();

Wenn Sie das Polygon nicht füllen möchten, verwenden Sie die Stroke () -Methode anstelle von fill ().

Sie können auch Folgendes überprüfen: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Vielen Dank

ankur
quelle
1

Verwenden Sie zusätzlich zu @canvastag eine whileSchleife, die shiftmeiner Meinung nach prägnanter ist:

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.
quelle
0

Verwenden Sie einfach die Funktion beginPath (), um ein einfaches Sechseck ohne Schleife zu erstellen. Stellen Sie sicher, dass Ihr canvas.getContext ('2d') gleich ctx ist, wenn dies nicht der Fall ist .

Ich möchte auch eine Variable namens times hinzufügen, mit der ich das Objekt bei Bedarf skalieren kann. Dies ist, was ich nicht brauche, um jede Zahl zu ändern.

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

Für die Leute, die nach regulären Polygonen suchen:

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

Verwenden:

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