Jak narysować wielokąty na płótnie HTML5?


95

Muszę wiedzieć, jak narysować wielokąty na płótnie. Bez używania jQuery lub czegoś podobnego.


10
Warto pamiętać, że cokolwiek można zrobić bez biblioteki innej firmy, należy to zwykle zrobić.
Rodrigo

Odpowiedzi:


165

Utwórz ścieżkę za pomocą moveToi lineTo( demo na żywo ):

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 nie dba o płótno, to twoja przeglądarka. jsFiddle po prostu przesyła z powrotem twój HTML / CSS / JS.
mu jest za krótkie

2
Doskonałe rozwiązanie. Bardzo zgrabny kod. dziękuję @phihag. Coś, co rozumiem!
obejrzyj

1
czy możesz zamienić c2 na ctx? Myślę, że jest to bardziej powszechne użycie w kontekście płótna. tak przy okazji świetna odpowiedź
gididaf

@ user1893354 Dziękuję bardzo za powiadomienie. Rzeczywiście wydaje się, że jest tam problem z jsfiddle - komunikat o błędzie jest całkowicie niezwiązany z kanwą. Zastąpiona bardzo prostą witryną demonstracyjną na żywo.
phihag

36

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

Poniższy kod narysuje sześciokąt. Zmień liczbę boków, aby utworzyć różne regularne wielokąty.

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
To było świetne, bardzo eleganckie, jeśli dodasz: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Możesz wypełnić kształt.
samuelkobe

to jest świetne - siedziałem, bawiąc się tym, ale nie mogę wymyślić, w jaki sposób obrócić wybrany wielokąt - jakieś pomysły?
eskimomatt

1
Jest kilka sposobów na zdobycie tego, czego chcesz. Jedną z opcji jest użycie wbudowanej metody cxt.rotate () [wraz z cxt.save () i cxt.restore ()] do obracania części płótna. Alternatywnie, zadziała również dodanie stałej wartości do funkcji cos i sin. Zobacz to jsfiddle, aby zobaczyć demonstrację: jsfiddle.net/kwyhn3ba
Andrew

dzięki za to - natknąłem się na to samo rozwiązanie po przeczytaniu logiki w podanym przez Ciebie łączu do nauki. var angle = i * 2 * Math.PI / shape.currentSides + rotationdodane do wartości cos i sin zadziałały dla mnie ... jeszcze raz dziękuję
eskimomatt

Jeśli (tak jak w moim przypadku) chcesz po prostu, aby punktem początkowym był środkowy wierzchołek wielokąta, a nie środkowy prawy, odwróć sini coswywołaj i zmień Ycenter +na Ycenter -w obu miejscach (pozostawiając to jako sumę, a nie różnicę wartości powoduje, że zaczyna się od punktu na dole powstałego kształtu). Nie jestem mądrym człowiekiem, jeśli chodzi o trygonometrię, więc bierz to z przymrużeniem oka; ale to osiągnęło to, co chciałem przynajmniej.
Joseph Marikle

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

Dlatego chciałbym zasadniczo zrozumieć formetodę waniliową JavaScript . Ta jedna linia kodu tak bardzo uprościła sprawę. Zwykle używam jQuery, .each()ale jego aplikacja jest znacznie mniej wszechstronna.
Alexander Dixon,

7
@AlexanderDixon Powyższy javascript nie jest dobrym przykładem. Wszystkie zmienne potrzebują var, w powyższym kodzie itemjest zanieczyszczenie globalnej przestrzeni nazw. Wszystko jest w jednej linii, co zmniejsza czytelność. Jeśli nie zależy Ci na czytelności, równie dobrze możesz usunąć nawiasy klamrowe.
AnnanFay,

@canvastag Dobra praca, dynamiczna praca. Ta odpowiedź jest lepsza od zaakceptowanej dla mnie odpowiedzi. Nie rozumiem "Query .each ()" ... to jest jakaś magiczna funkcja, która zajmuje pamięć. Również dla globalnej przestrzeni nazw;) zabawne, to tylko przykład uczynienia go podobnym do klasy, jeśli chcesz.
Nikola Lukic

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

Ciekawe ... Właściwie to ruchTo ORAZ liniaTo na początek ... ale teraz, kiedy o tym myślę ... kogo to obchodzi?
James Newton,

3

Oto funkcja, która obsługuje nawet rysowanie zgodnie z ruchem wskazówek zegara / przeciwnie do ruchu wskazówek zegara, dzięki której kontrolujesz wypełnienia za pomocą niezerowej reguły nawijania.

Oto pełny artykuł o tym, jak to działa i nie tylko.

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

Ten artykuł jest dość obszerny, by powiedzieć „rysujesz koło o mniejszych krawędziach”. Możesz chcieć zapisać wyniki w pamięci podręcznej, aby uniknąć wywoływania cos i sin tak często (wybacz mi, jeśli już to robi, nie jestem programistą JavaScript).
QuantumKarl

1

Możesz użyć metody lineTo () tak samo jak: 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();

jeśli nie chcesz wypełniać wielokąta, użyj metody stroke () zamiast wypełnienia ()

Możesz również sprawdzić: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

dzięki


1

Oprócz @canvastag użyj whilepętli, która shiftmoim zdaniem jest bardziej zwięzła:

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

Aby utworzyć prosty sześciokąt bez potrzeby tworzenia pętli, wystarczy użyć funkcji beginPath (). Upewnij się, że plik canvas.getContext ('2d') jest równy ctx, jeśli nie, to nie zadziała.

Lubię też dodawać zmienną o nazwie czasy, której mogę użyć do skalowania obiektu, jeśli zajdzie taka potrzeba, ale nie muszę zmieniać każdej liczby.

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

Dla osób poszukujących regularnych wielokątów:

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

Posługiwać się:

//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();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.