2011-11-06 127 views
19

正如標題所述。這可能嗎?如何用HTML5畫布繪製甜甜圈的分段?

編輯:當我說甜甜圈我的意思是一個頂,2D視圖

是畫一個圓缺的唯一選擇,再畫一個小圓圈的部分用相同的起源和較小的半徑在頂部,背景的顏色?如果是這樣,這將是廢話:(

回答

29

您通過使單一路徑與兩條弧線做到這一點。

順時針繪製一個圓,然後逆時針繪製第二個圓。我不會詳細討論它的細節,但路徑構建的方式知道將其作爲取消路徑的一部分的理由。有關它在做什麼的更多細節,你可以this wiki article

如果您正在繪製「框架」矩形,則同樣可行。您單向(順時針)繪製一個盒子,然後以另一種方式(逆時針)繪製內盒以獲得效果。

下面是一個甜甜圈代碼:

var can = document.getElementById('canvas1'); 
var ctx = can.getContext('2d'); 

// Pay attention to my last argument! 
//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); 

ctx.beginPath() 
ctx.arc(100,100,100,0,Math.PI*2, false); // outer (filled) 
ctx.arc(100,100,55,0,Math.PI*2, true); // inner (unfills it) 
ctx.fill(); 

實例:繪製只是一個「片段」它可以使道路更小做

http://jsfiddle.net/Hnw6a/

(您可能需要使用beziers而不是arc),或者使用裁剪區域。這真的取決於你如何到底要「段」

這裏有一個例子:http://jsfiddle.net/Hnw6a/8/

// half doughnut 
ctx.beginPath() 
ctx.arc(100,100,100,0,Math.PI, false); // outer (filled) 
ctx.arc(100,100,55,Math.PI,Math.PI*2, true); // outer (unfills it) 
ctx.fill(); 
+0

aha!這看起來就像我需要的,謝謝! –

+1

而不是填充和不填充,爲什麼不只是用寬度的中風? – Phrogz

+0

@Progrog你可能想要邊框和填充爲不同的顏色。 – 2012-01-11 15:30:51

1
+0

澄清的問題,我的意思在2D遺憾。你的答案仍然適用? –

+0

@AndrewBullock它適用於「有點」 - 你也可以使用2D的WebGL,它應該提供更多的選項來展現你想要繪製的內容......對於WebGL中的簡單2D示例,請參閱https://developer.mozilla.org/en/WebGL/Adding_2D_content_to_a_WebGL_context – Yahia

3

您可以通過撫摸弧做出「頂視圖甜甜圈」(圓空心中心)。你可以在這裏看到這樣一個例子:http://phrogz.net/tmp/connections.html

enter image description here

圓圈(帶針頭)由線239-245得出:

ctx.lineWidth = half*0.2;   // set a nice fat line width 
var r = half*0.65;     // calculate the radius 
ctx.arc(0,0,r,0,Math.PI*2,false); // create the circle part of the path 
// ... some commands for the nib 
ctx.stroke();      // actually draw the path 
1

給出的要求,什麼@SimonSarris說滿足問題。但讓我們說你和我一樣,而你卻想要「清除」一部分可能部分超出你正在清理的形狀範圍的形狀。如果你有這個要求,他的解決方案不會讓你想要你想要的。它看起來像下圖中的「xor」。

enter image description here

的解決方案是使用context.globalCompositeOperation = 'destination-out'藍色是所述第一形狀和所述紅色是第二形狀。如您所見,destination-out將刪除第一個形狀的部分。下面是一些示例代碼:

explosionCanvasCtx.fillStyle = "red" 
    drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

    explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 
    drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

下面是這個潛在的問題:第二fill()將清除一切它的下面,包括背景。有時您只想清除第一個形狀,但您仍然希望看到它下面的圖層。

解決方案是在臨時畫布上繪製此圖像,然後使用drawImage將臨時畫布繪製到主畫布上。該代碼將是這樣的:

diameter = projectile.radius * 2 
    console.log "<canvas width='" + diameter + "' height='" + diameter + "'></canvas>" 
    explosionCanvas = $("<canvas width='" + diameter + "' height='" + diameter + "'></canvas>") 
    explosionCanvasCtx = explosionCanvas[0].getContext("2d") 

    explosionCanvasCtx.fillStyle = "red" 
    drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

    explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 
    durationPercent = (projectile.startDuration - projectile.duration)/projectile.startDuration 
    drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 
    explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 

    ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center 
2

是的,我明白這個問題有多老:)

這裏是我的兩分錢:

(function(){ 
var annulus = function(centerX, centerY, 
         innerRadius, outerRadius, 
         startAngle, endAngle, 
         anticlockwise) { 
    var th1 = startAngle*Math.PI/180; 
    var th2 = endAngle*Math.PI/180; 
    var startOfOuterArcX = outerRadius*Math.cos(th2) + centerX; 
    var startOfOuterArcY = outerRadius*Math.sin(th2) + centerY; 

    this.beginPath(); 
    this.arc(centerX, centerY, innerRadius, th1, th2, anticlockwise); 
    this.lineTo(startOfOuterArcX, startOfOuterArcY); 
    this.arc(centerX, centerY, outerRadius, th2, th1, !anticlockwise); 
    this.closePath(); 
} 
CanvasRenderingContext2D.prototype.annulus = annulus; 
})(); 

這將增加一個功能「輪( )「類似於CanvasRenderingContext2D原型中的」arc()「。如果你想檢查點包含,使閉合路徑派上用場。

有了這個功能,你可以這樣做:

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
ctx.annulus(0, 0, 100, 200, 15, 45); 
ctx.fill(); 

或者檢查了這一點:https://jsfiddle.net/rj2r0k1z/10/

謝謝!

+0

謝謝。今天我會用很多:) – T4NK3R

0

適配/簡化@Simon薩里斯的回答容易地與任何角度工作給出以下:

要創建一個圓弧段你在一個方向上繪製的外弧(的n爲弧度),然後相對的圓弧(的相同的弧度數)以較小的半徑填充所得區域。

var can = document.getElementById('canvas1'); 
 
var ctx = can.getContext('2d'); 
 
    
 
var angle = (Math.PI*2)/8; 
 

 
var outer_arc_radius = 100; 
 
var inner_arc_radius = 50.; 
 

 
ctx.beginPath() 
 

 
//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); 
 
ctx.arc(100,100,outer_arc_radius,0,angle, false); // outer (filled) 
 
// the tip of the "pen is now at 0,100 
 
ctx.arc(100,100,inner_arc_radius,angle,0, true); // outer (unfills it) 
 
ctx.fill();
<canvas id="canvas1" width="200" height="200"></canvas>