Bir HTML5 tuvalinde çokgenler nasıl çizilir?


97

Çokgenleri bir tuval üzerine nasıl çizeceğimi bilmem gerekiyor. JQuery veya benzeri bir şey kullanmadan.


10
Üçüncü taraf bir kitaplık olmadan yapılabilecek her şeyin genellikle yapılması gerektiğini hatırlamakta fayda var.
Rodrigo

Yanıtlar:


168

moveToVe lineTo( canlı demo ) ile bir yol oluşturun :

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 tuvali umursamıyor, bu sizin tarayıcınız. jsFiddle sadece HTML / CSS / JS'nizi size geri gönderir.
mu çok kısa

2
Mükemmel çözüm. Çok düzgün kod. teşekkür ederim @phihag. Anlayabileceğim bir şey!
bytise

1
c2'yi ctx ile değiştirebilir misin? Tuval bağlamı için daha yaygın bir kullanım olduğunu düşünüyorum. bu arada harika cevap
gididaf

@ user1893354 Bildirim için çok teşekkür ederim. Aslında, orada jsfiddle ile ilgili bir sorun var gibi görünüyor - hata mesajı tuval ile tamamen alakasız. Çok basit bir canlı demo sitesi ile değiştirildi.
phihag

36

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

Aşağıdaki kod bir altıgen çizecektir. Farklı normal çokgenler oluşturmak için kenarların sayısını değiştirin.

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
Bu da harikaydı, çok zarifti, eklerseniz: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Şekli doldurabilirsiniz.
samuelkobe

bu harika - oturup onunla oynuyordum, ancak seçilen çokgeni nasıl döndüreceğimi çözemiyorum - herhangi bir fikir?
eskimomatt

1
İstediğinizi elde etmenin birkaç yolu var. Bir seçenek, tuvalin parçalarını döndürmek için yerleşik cxt.rotate () yöntemini [cxt.save () ve cxt.restore () ile birlikte] kullanmaktır. Alternatif olarak, cos ve sin işlevlerine tutarlı bir değer eklemek de işe yarayacaktır. Bir gösteri için bu jsfiddle'ı görün: jsfiddle.net/kwyhn3ba
Andrew Staroscik

bunun için teşekkürler - sağladığınız bilim primer bağlantısındaki mantığı okuduktan sonra aynı çözüme rastladım. var angle = i * 2 * Math.PI / shape.currentSides + rotationbenim için çalıştı cos ve sin değerlerine eklendi ... tekrar teşekkürler
eskimomatt

(Benim durumumda olduğu gibi) sadece istiyorsanız başlangıç noktası çevirmek yerine orta sağa göre çokgenin orta üst olmak sinve cosaramaları ve değişim Ycenter +için Ycenter -(her iki yerde değerlerin bir fark yerine bir toplamı olarak bırakmak sonuçta ortaya çıkan şeklin altındaki bir nokta ile başlar). Trig söz konusu olduğunda akıllı bir adam değilim, bu yüzden biraz tuzla alın; ama bu en azından istediğimi başardı.
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();

Bu yüzden keşke JavaScript vanilya foryöntemini temelden anlayabilseydim . Bu tek satırlık kod işleri çok basitleştirdi. Genelde jQuery kullanıyorum .each()ama uygulaması çok daha az çok yönlü.
Alexander Dixon

8
@AlexanderDixon Yukarıdaki javascript gerçekten iyi bir örnek değil. Yukarıdaki koddaki tüm değişkenlerin ihtiyacı var, itemküresel isim alanını kirletmektir. Her şey tek satırda, bu da okunabilirliği azaltır. Okunabilirliği önemsemiyorsanız, süslü parantezleri de kaldırabilirsiniz.
AnnanFay

@canvastag Güzel iş dinamik iş. Bu cevap benim için kabul edilmiş cevaptan daha iyidir. "Query .each ()" anlamıyorum ... bu hafızayı alan sihirli bir işlev. Ayrıca global isim alanı için;) komik bu sadece bir örnektir, eğer isterseniz onu sınıf gibi yapın.
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');

İlginç ... Aslında ilk noktaya VE bir çizgiye hareket ediyor ... ama şimdi düşünüyorum da ... kimin umurunda?
James Newton

3

İşte sıfır olmayan sarma kuralı ile dolguları kontrol ettiğinizde saat yönünde / saat yönünün tersine çizimi destekleyen bir fonksiyon.

İşte nasıl çalıştığı ve daha fazlası hakkında tam bir makale.

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

Bu makale, "daha az kenarlı bir çember çiziyorsun" demek için oldukça uzun. Cos ve çok günah çağırmaktan kaçınmak için sonuçları önbelleğe almak isteyebilirsiniz (zaten yapıyorsa beni affet, ben JavaScript programcısı değilim).
QuantumKarl

1

LineTo () yöntemini şu şekilde kullanabilirsiniz: 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();

çokgeni doldurmak istemiyorsanız, fill () yerine strok () yöntemini kullanın

Ayrıca şunları da kontrol edebilirsiniz: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Teşekkürler


1

@Canvastag'e ek olarak, bence daha kısa bir whiledöngü kullanın shift:

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

Döngüye ihtiyaç duymadan basit bir altıgen yapmak için, sadece beginPath () işlevini kullanın. Emin olun canvas.getContext ( '2d') eşittir CTX değil iş olmaz eğer.

Ayrıca, ihtiyaç duyarsam nesneyi ölçeklendirmek için kullanabileceğim zamanlar adı verilen bir değişken eklemeyi seviyorum.

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

Normal çokgen arayanlar için:

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

Kullanım:

//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();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.