Як намалювати багатокутники на полотні HTML5?


95

Мені потрібно знати, як намалювати багатокутники на полотні. Без використання jQuery або чогось подібного.


10
Варто пам’ятати, що все, що можна зробити без сторонньої бібліотеки, зазвичай повинно робити це.
Родріго

Відповіді:


165

Створіть шлях за допомогою moveToі lineTo( жива демонстрація ):

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 не дбає про полотно, це ваш браузер. jsFiddle просто передає вам ваш HTML / CSS / JS.
му занадто коротке

2
Відмінне рішення. Дуже акуратний код. дякую u @phihag. Щось, що я можу зрозуміти!
bytise

1
Ви можете замінити c2 на ctx? Я думаю, це частіше використовується для контексту полотна. чудова відповідь до речі
gididaf

@ user1893354 Щиро дякую за повідомлення. Справді, там, здається, проблема з jsfiddle - повідомлення про помилку абсолютно не пов'язане з полотном. Замінено на дуже простий демонстраційний сайт.
phihag

35

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

Наступний код намалює шестикутник. Змініть кількість сторін, щоб створити різні правильні багатокутники.

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
Це було чудово, дуже елегантно, також, якщо додати: cxt.save(); cxt.fillStyle = "#FF000"; cxt.fill(); cxt.restore(); Ви можете заповнити форму.
samuelkobe

це чудово - я сидів із нею, але не можу зрозуміти, як би я змусив обернути обраний багатокутник - будь-які ідеї?
ескімомат

1
Є кілька способів отримати бажане. Одним із варіантів є використання вбудованого методу cxt.rotate () [разом із cxt.save () та cxt.restore ()] для обертання частин полотна. Крім того, додавання послідовного значення до функцій cos та sin також буде працювати. Див. Цей jsfiddle для демонстрації: jsfiddle.net/kwyhn3ba
Andrew Staroscik

дякую за це - я натрапив на те саме рішення, прочитавши логіку на посиланні, яке ви надали. var angle = i * 2 * Math.PI / shape.currentSides + rotationдодані до значень cos та sin працювали для мене ... ще раз спасибі
ескімомат

Якщо (як в моєму випадку) , ви просто хочете відправною точкою , щоб бути в середині верхньої частини полігону , а не середнього права, перевертати sinі cosвиклики і зміни Ycenter +в Ycenter -обох місцях (залишаючи його у вигляді суми , а не різниці значень в результаті це починається з точки внизу результуючої фігури). Я не розумний чоловік, коли справа доходить до тригеру, тож візьміть із зерном солі; але це досягло того, що я хотів щонайменше.
Джозеф Марікле

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

Ось чому я хотів би принципово зрозуміти forметод ванільного JavaScript . Цей рядок коду настільки спростив ситуацію. Зазвичай я використовую jQuery, .each()але його додаток набагато менш універсальний.
Олександр Діксон,

7
@AlexanderDixon Наведений вище javascript насправді не є гарним прикладом. Усі змінні потребують var, у наведеному вище коді itemзабруднюється глобальний простір імен. Все на одному рядку, що зменшує читабельність. Якщо ви не дбаєте про читабельність, тоді ви можете також видалити фігурні дужки.
AnnanFay

@canvastag Гарна робота, динамічна робота. Ця відповідь краще, ніж прийнята для мене відповідь. Я не розумію "Query .each ()" ... це якась магічна функція, яка займає пам'ять. Також для глобального простору імен;) смішно, це лише приклад, зробіть це як клас, якщо хочете.
Нікола Лукіч

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

Цікаво ... Насправді робить переміщення НА І рядок До першого пункту ... але тепер, коли я про це думаю ... кому все одно?
James Newton

3

Ось функція, яка навіть підтримує креслення за годинниковою стрілкою / проти годинникової стрілки, щоб контролювати заливки за допомогою ненульового правила обмотки.

Ось повна стаття про те, як це працює, та багато іншого.

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

У цій статті досить довго говорити "ви малюєте коло з меншими краями". Можливо, ви захочете кешувати результати, щоб уникнути викликів cos і sin так сильно (пробачте мене, якщо це вже робиться, я не програміст JavaScript).
QuantumKarl

1

Ви можете використовувати метод lineTo () так само, як: 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();

якщо ви не хочете заповнювати багатокутник, використовуйте метод stroke () замість fill ()

Ви також можете перевірити наступне: http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/

Дякую


1

На додаток до @canvastag, використовуйте whileцикл із, на 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

Щоб зробити простий шестикутник без необхідності циклу, Просто використовуйте функцію beginPath (). Переконайтеся, що ваш canvas.getContext ('2d') дорівнює ctx, якщо ні, він не буде працювати.

Мені також подобається додавати змінну, яка називається times, яку я можу використати для масштабування об'єкта, якщо мені це потрібно. Це те, що мені не потрібно змінювати кожне число.

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

Для людей, які шукають правильні багатокутники:

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

Використання:

//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();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.