Como desenhar polígonos em uma tela HTML5?


95

Preciso saber desenhar polígonos em uma tela. Sem usar jQuery ou algo parecido.


10
É bom lembrar que tudo o que pode ser feito sem uma biblioteca de terceiros, geralmente deve ser feito.
Rodrigo

Respostas:


165

Crie um caminho com moveToe lineTo( demonstração ao 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 não liga para o canvas, esse é o seu navegador. jsFiddle apenas envia seu HTML / CSS / JS de volta para você.
mu é muito curto

2
Excelente solução. Código muito bom. obrigado @phihag. Algo que eu possa entender!
bytise

1
você pode substituir c2 por ctx? Acho que é o uso mais comum para o contexto do canvas. ótima resposta, por
falar

@ user1893354 Muito obrigado pelo aviso. Na verdade, parece haver um problema com o jsfiddle ali - a mensagem de erro não está totalmente relacionada ao canvas. Substituído por um site de demonstração ao vivo muito simples.
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();

É por isso que eu gostaria de poder entender fundamentalmente o formétodo JavaScript vanilla . Essa única linha de código simplificou muito as coisas. Normalmente uso o jQuery, .each()mas seu aplicativo é muito menos versátil.
Alexander Dixon

7
@AlexanderDixon O javascript acima não é realmente um bom exemplo. Todas as variáveis ​​precisam var, no código acima itemestá poluindo o namespace global. Tudo está em uma linha, o que reduz a legibilidade. Se você não se preocupa com a legibilidade, pode também remover as chaves.
AnnanFay

@canvastag Bom trabalho, trabalho dinâmico. Esta resposta é melhor de uma resposta aceita por mim. Não entendo "Query .each ()" ... esta é uma função mágica que ocupa memória. Também para namespace global;) engraçado, este é apenas um exemplo, faça como uma classe se você quiser.
Nikola Lukic

34

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

O código a seguir desenhará um hexágono. Altere o número de lados para criar 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
Isso foi ótimo, muito elegante, também, se você adicionar: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Você pode preencher a forma.
samuelkobe

isso é ótimo - estive sentado brincando com ele, mas não consigo descobrir como faria o polígono escolhido girar - alguma ideia?
eskimomatt

1
Existem algumas maneiras de obter o que deseja. Uma opção é usar o método cxt.rotate () embutido [junto com cxt.save () e cxt.restore ()] para girar partes da tela. Como alternativa, adicionar um valor consistente às funções cos e sin também funcionará. Veja este jsfiddle para uma demonstração: jsfiddle.net/kwyhn3ba
Andrew Staroscik

obrigado por isso - encontrei a mesma solução depois de ler a lógica no link de introdução científica que você forneceu. var angle = i * 2 * Math.PI / shape.currentSides + rotationadicionado aos valores de cos e sin funcionou para mim ... obrigado novamente
eskimomatt

Se (como no meu caso) você quiser apenas que o ponto de partida seja o topo do meio do polígono em vez do meio à direita, vire sine coschama e mude Ycenter +para Ycenter -em ambos os lugares (deixando como uma soma em vez de uma diferença de valores resulta em começar com um ponto na parte inferior da forma resultante). Não sou um homem inteligente quando se trata de trigonometria, então aceite com cautela; mas isso atingiu o que eu queria, pelo menos.
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 ... Na verdade, moveTo AND lineTo para o primeiro ponto ... mas agora que penso nisso ... quem se importa?
James Newton

3

Aqui está uma função que suporta até mesmo o desenho no sentido horário / anti-horário que você controla os preenchimentos com a regra de contorno diferente de zero.

Aqui está um artigo completo sobre como funciona e muito mais.

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

Esse artigo é bastante longo para dizer "você está desenhando um círculo com menos arestas". Você pode querer armazenar em cache os resultados para evitar chamar tanto cos e sin (perdoe-me se já estou fazendo isso, não sou um programador de JavaScript).
QuantumKarl

1

Você pode usar o método lineTo () igual a: 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 você não quiser preencher o polígono, use o método stroke () no lugar do fill ()

Você também pode verificar o seguinte: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

obrigado


1

Além de @canvastag, use um whileloop com shiftacho que é mais 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 fazer um hexágono simples sem a necessidade de um loop, basta usar a função beginPath (). Certifique-se de que seu canvas.getContext ('2d') seja igual a ctx, caso contrário, não funcionará.

Também gosto de adicionar uma variável chamada times que posso usar para dimensionar o objeto se precisar. Isso é o que não preciso alterar 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 as pessoas que procuram 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);
}

Usar:

//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();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.