Bagaimana cara menggambar poligon pada kanvas HTML5?

95

Saya perlu tahu cara menggambar poligon di atas kanvas. Tanpa menggunakan jQuery atau semacamnya.

CyanPrime
sumber
10
Perlu diingat bahwa apa pun yang dapat dilakukan tanpa perpustakaan pihak ketiga, biasanya harus dilakukan.
Rodrigo

Jawaban:

165

Buat jalur dengan moveTodan lineTo( demo langsung ):

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
sumber
100
@ Gio Borje: AFAIK, jsFiddle tidak peduli dengan kanvas, itu browser Anda. jsFiddle hanya memberikan HTML / CSS / JS Anda kembali kepada Anda.
mu terlalu pendek
2
Solusi luar biasa. Kode yang sangat rapi. terima kasih @phihag. Sesuatu yang bisa saya mengerti!
bytise
1
dapatkah anda mengganti c2 dengan ctx? Saya pikir itu lebih umum digunakan untuk konteks kanvas. jawaban yang bagus omong-omong
gididaf
@ user1893354 Terima kasih banyak atas pemberitahuannya. Memang, tampaknya ada masalah dengan jsfiddle di sana - pesan kesalahan sama sekali tidak terkait dengan kanvas. Digantikan dengan situs demo langsung yang sangat sederhana.
phihag
36

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

Kode berikut akan menggambar segi enam. Ubah jumlah sisi untuk membuat poligon beraturan yang berbeda.

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
sumber
3
Ini bagus, sangat elegan, juga, jika Anda menambahkan: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Anda dapat mengisi bentuknya.
samuelkobe
ini bagus - saya sudah duduk bermain dengannya, tetapi tidak tahu bagaimana saya akan mendapatkan poligon yang dipilih untuk diputar - ada ide?
eskimomatt
1
Ada beberapa cara untuk mendapatkan apa yang Anda inginkan. Salah satu opsinya adalah menggunakan metode cxt.rotate () bawaan [bersama dengan cxt.save () dan cxt.restore ()] untuk memutar bagian kanvas. Selain itu, menambahkan nilai yang konsisten ke fungsi cos dan sin juga akan berfungsi. Lihat jsfiddle ini untuk demonstrasi: jsfiddle.net/kwyhn3ba
Andrew Staroscik
terima kasih untuk itu - saya menemukan solusi yang sama setelah membaca logika pada tautan primer sains yang Anda berikan. var angle = i * 2 * Math.PI / shape.currentSides + rotationditambahkan ke cos dan nilai dosa bekerja untuk saya ... terima kasih lagi
eskimomatt
Jika (seperti dalam kasus saya) Anda hanya ingin titik awal untuk menjadi bagian atas tengah poligon daripada tengah kanan, flip sindan cospanggilan dan perubahan Ycenter +untuk Ycenter -di kedua tempat (meninggalkan sebagai sum daripada perbedaan dari nilai-nilai menghasilkan itu dimulai dengan titik di bagian bawah bentuk yang dihasilkan). Saya bukan orang pintar dalam hal trigonometri, jadi ambillah dengan sebutir garam; tetapi ini setidaknya mencapai apa yang saya inginkan.
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();
kanvas
sumber
Inilah sebabnya saya berharap saya bisa memahami secara mendasar formetode vanilla JavaScript . Satu baris kode itu sangat menyederhanakan banyak hal. Saya biasanya menggunakan jQuery .each()tetapi aplikasinya kurang fleksibel.
Alexander Dixon
7
@AlexanderDixon Javascript di atas sebenarnya bukan contoh yang baik. Semua variabel perlu var, dalam kode di atas itemadalah mencemari namespace global. Semuanya dalam satu baris, yang mengurangi keterbacaan. Jika Anda tidak peduli dengan keterbacaan maka Anda sebaiknya menghapus tanda kurung keriting.
AnnanFay
@canvastag Kerja bagus, pekerjaan dinamis. Jawaban ini lebih baik dari jawaban yang diterima untuk saya. Saya tidak mengerti "Query .each ()" ... ini adalah beberapa fungsi ajaib yang mengambil memori. Juga untuk namespace global;) lucu ini hanya contoh membuatnya seperti kelas jika Anda menginginkannya.
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');
Jignesh Variya
sumber
Menarik ... Sebenarnya bergerak Ke DAN garis Ke untuk poin pertama ... tapi sekarang saya memikirkannya ... siapa yang peduli?
James Newton
3

Berikut adalah fungsi yang bahkan mendukung gambar searah jarum jam / berlawanan arah jarum jam yang Anda kontrol isinya dengan aturan belitan bukan nol.

Berikut adalah artikel lengkap tentang cara kerjanya dan banyak lagi.

// 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
sumber
Artikel itu agak panjang untuk mengatakan "Anda menggambar lingkaran dengan sedikit tepi". Anda mungkin ingin menyimpan hasil untuk menghindari pemanggilan cos dan dosa begitu banyak (maafkan saya jika sudah melakukannya, saya bukan pemrogram JavaScript).
QuantumKarl
1

Anda bisa menggunakan metode lineTo () yang sama seperti: 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();

jika Anda tidak ingin mengisi poligon gunakan metode stroke () sebagai ganti fill ()

Anda juga dapat memeriksa yang berikut ini: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Terima kasih

ankur
sumber
1

Selain @canvastag, gunakan whileloop dengan yang shiftmenurut saya lebih ringkas:

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

Untuk membuat segi enam sederhana tanpa membutuhkan loop, cukup gunakan fungsi beginPath (). Pastikan canvas.getContext ('2d') Anda sama dengan ctx jika tidak, ini tidak akan berfungsi.

Saya juga suka menambahkan variabel bernama times yang dapat saya gunakan untuk menskalakan objek jika perlu. Ini yang tidak perlu saya ubah setiap angka.

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

Untuk orang yang mencari poligon beraturan:

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

Menggunakan:

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