使用<canvas>
標籤我需要能夠在多邊形中繪製一個孔。帶有HTML5畫布中間的孔的多邊形
現在我有一些非常簡單的使用beginPath(),然後爲每個點做lineTo()。然後填充fill()。
我看不出有什麼辦法讓一個填充的多邊形與一個未填充的中間,但像一個甜甜圈。 我不是做甜甜圈,但它適合這個例子。
有什麼我失蹤? 我寧願不把它填滿,然後不得不重新繪製中間。
使用<canvas>
標籤我需要能夠在多邊形中繪製一個孔。帶有HTML5畫布中間的孔的多邊形
現在我有一些非常簡單的使用beginPath(),然後爲每個點做lineTo()。然後填充fill()。
我看不出有什麼辦法讓一個填充的多邊形與一個未填充的中間,但像一個甜甜圈。 我不是做甜甜圈,但它適合這個例子。
有什麼我失蹤? 我寧願不把它填滿,然後不得不重新繪製中間。
這是我做它的工作:
var ctx = canvas.getContext("2d");
ctx.beginPath();
//polygon1--- usually the outside polygon, must be clockwise
ctx.moveTo(0, 0);
ctx.lineTo(200, 0);
ctx.lineTo(200, 200);
ctx.lineTo(0, 200);
ctx.lineTo(0, 0);
ctx.closePath();
//polygon2 --- usually hole,must be counter-clockwise
ctx.moveTo(10, 10);
ctx.lineTo(10,100);
ctx.lineTo(100, 100);
ctx.lineTo(100, 10);
ctx.lineTo(10, 10);
ctx.closePath();
// add as many holes as you want
ctx.fillStyle = "#FF0000";
ctx.strokeStyle = "rgba(0.5,0.5,0.5,0.5)";
ctx.lineWidth = 1;
ctx.fill();
ctx.stroke();
這裏的主要想法是,你只能使用一次beginPath方法;外面的多邊形必須是順時針的,孔必須是逆時針的。
完美,應接受IMO。 –
它工作完美,但我現在想知道有沒有機會按順時針或逆時針順序點。我發現了一些算法,但沒有一個不能用於非凸多邊形。 –
在我看來,對於外部多邊形和反向孔的方向不一定是順時針的 - 它們只需要相反。上下文假定第一個輸入多邊形的方向爲_right_,至少在Chrome中。 –
您有2個選擇可以用HTML5畫布繪製孔。
選擇1:
在不同的時鐘方向繪製外部形狀和內部形狀。
外形順時針和內形逆時針。
或順時針外形和逆時針內形。
ctx.beginPath();
//outer shape, clockwise
ctx.moveTo(100,20);
ctx.lineTo(200,200);
ctx.lineTo(20,200);
ctx.closePath();
//inner shape (hole), counter-clockwise
ctx.moveTo(100,100);
ctx.lineTo(70,170);
ctx.lineTo(140,170);
ctx.closePath();
//fill
ctx.fillStyle = "#FF0000";
ctx.fill();
當我們編碼時,檢測形狀繪製方向有點痛苦。
如果需要檢測一系列的點是順時針還是不行,這裏是一個不錯的功能:
function isClockwise(dots){
var sum = 0;
for(var i=1, n=dots.length; i<n; i++){
sum += (dots[i][0] - dots[i-1][0]) * (dots[i][1] + dots[i-1][1]);
}
sum += (dots[0][0] - dots[n-1][0]) * (dots[0][1] + dots[n-1][1]);
return sum < 0;
}
console.log(isClockwise([[100,20], [200,200], [20,200]])); //true
console.log(isClockwise([[100,20], [20,200], [200,200]])); //false
如果你的點是順時針的,但你需要逆時針,.reverse()你點陣列。
var dots = [[100,20], [200,200], [20,200]];
dots.reverse();
選擇2:
使用 'EVENODD' 補規則,畫出你的形狀在任何方向。
這種方式比選擇1
看到fill() method API簡單得多:
void ctx.fill();
void ctx.fill(fillRule);
void ctx.fill(path, fillRule);
fillRule可以「非零」或「EVENODD」
「非零」:在非零繞線規則,這是默認規則。
「evenodd」:偶數的纏繞規則。
您可以使用evenodd填充規則:fill('evenodd')
// properties
// - outer square
var outerLength = 200;
// - inner length
var innerLength = outerLength/2;
// cnavas
var canvas = document.getElementById('canvas');
var width = canvas.width = document.body.clientWidth;
var height = canvas.height = document.body.clientHeight;
var context = canvas.getContext('2d');
// path
// - outer square
context.rect(
(width - outerLength)/2,
(height - outerLength)/2,
outerLength,
outerLength
);
// - inner square
var x0 = (width - innerLength)/2;
var y0 = (height - innerLength)/2;
context.moveTo(x0, y0);
context.rect(
x0,
y0,
innerLength,
innerLength
);
// draw
// - stroke
context.lineWidth = 10;
context.stroke();
// - fill
context.fillStyle = 'red';
context.fill('evenodd');
html,
body {
margin: 0;
height: 100%;
overflow: hidden;
}
<canvas id="canvas"><canvas>
你爲什麼不想要一個甜甜圈 ?甜甜圈很棒! 請參考此鏈接繪製形狀:https://developer.mozilla.org/en-US/docs/Canvas_tutorial/Drawing_shapes – jazzytomato
我同意甜甜圈值得一提。這個鏈接:http://www.w3schools.com/tags/ref_canvas.asp也可以是有用的。 – GameAlchemist
只是爲了澄清,我畫了一個複雜的多邊形與數百個點。甜甜圈只是在多邊形中間有一個洞的類比。 – Nick