2014-02-10 45 views
1

我想畫一個圓圈。但是,不是真的。我想要一系列弧線(分段),這意味着一整圈。它會旋轉,它會很棒。但我顯然做錯了什麼。 Please, check this fiddle: http://jsfiddle.net/utWdM/如何在畫布元素中正確繪製一個帶有空隙的圓?

function draw() { 
    var canvas = document.getElementById("canvas"); 
    if (canvas.getContext) { 
     var ctx = canvas.getContext("2d"); 
     ctx.lineWidth = 15; 
     ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)'; 
     ctx.beginPath(); 

     ctx.arc(250, 250, 100, 0, Math.PI * 8/30); 
     ctx.moveTo(250, 250); 
     ctx.arc(250, 250, 100, Math.PI * 12/30, Math.PI * 20/30); 
     ctx.moveTo(250, 250); 
     ctx.arc(250, 250, 100, Math.PI * 24/30, Math.PI * 32/30); 
     ctx.moveTo(250, 250); 
     ctx.arc(250, 250, 100, Math.PI * 36/30, Math.PI * 44/30); 
     ctx.moveTo(250, 250); 
     ctx.arc(250, 250, 100, Math.PI * 48/30, Math.PI * 56/30); 

     ctx.stroke(); 
     ctx.closePath(); 
    } 
} 

draw(); 

我不想從中心到弧(和第一個不擁有它)開始行。 我一直在用畫布學習基本繪圖,希望能夠理解將來會發生什麼,甚至更多,但是我迫不及待地想知道在這種情況下出了什麼問題。 任何幫助,高度讚賞。

回答

1

對moveTo必須是圓弧不是中心的開始。如下所示,這很容易通過轉換到圓心來實現。 http://jsfiddle.net/utWdM/1

function draw() { 
    var canvas = document.getElementById("canvas"); 
    if (canvas.getContext) { 
     var ctx = canvas.getContext("2d"); 
     ctx.lineWidth = 15; 
     ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)'; 
     ctx.beginPath(); 

     ctx.translate(250,250); 
     ctx.arc(0, 0, 100, 0, Math.PI * 8/30); 
     ctx.moveTo(100*Math.cos(Math.PI*12/30), 100*Math.sin(Math.PI*12/30)); 
     ctx.arc(0, 0, 100, Math.PI * 12/30, Math.PI * 20/30); 
     ctx.moveTo(100*Math.cos(Math.PI*24/30), 100*Math.sin(Math.PI*24/30)); 
     ctx.arc(0, 0, 100, Math.PI * 24/30, Math.PI * 32/30); 
     ctx.moveTo(100*Math.cos(Math.PI*36/30), 100*Math.sin(Math.PI*36/30)); 
     ctx.arc(0, 0, 100, Math.PI * 36/30, Math.PI * 44/30); 
     ctx.moveTo(100*Math.cos(Math.PI*48/30), 100*Math.sin(Math.PI*48/30)); 
     ctx.arc(0, 0, 100, Math.PI * 48/30, Math.PI * 56/30); 

     ctx.stroke(); 
     ctx.closePath(); 
    } 
} 
+0

+1好答案。注意:由於您在draw()中進行翻譯,因此可能需要使用ctx.save/ctx.restore進行換行。否則,任何進一步調用draw()都會累積轉換並將繪圖從畫布中驅出。除了提問者需要的內容之外:由於您已經在翻譯中心點,因此您可以添加ctx.rotate(radianAngle),這將使您的弧形圓圈也可以旋轉。 – markE

+0

太棒了!正如小提琴所顯示的那樣,它有效,它幫助我更新了餘弦,正弦和單位圓的知識。這從現在起有所幫助,並且從長遠來看將是有用的。所以,非常感謝你! – slacktracer

+0

理解我應該在哪裏「轉向」以及如何計算它正是我所需要的。我想我幾乎是幾何學迷路了。 = P現在,「最終」產品在這裏可以看到它的全部榮耀!:http://anzol.biz/ – slacktracer

1

要避免複雜的數學運算,最簡單的方法是爲每個段調用.beginPath().stroke();。我知道這是很重複,但是,它會是什麼樣子:

function draw() { 
    var canvas = document.getElementById("canvas"); 
    if (canvas.getContext) { 
     var ctx = canvas.getContext("2d"); 
     ctx.lineWidth = 15; 
     ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)'; 

     ctx.beginPath();   
     ctx.arc(250, 250, 100, 0, Math.PI * 8/30); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.arc(250, 250, 100, Math.PI * 12/30, Math.PI * 20/30); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.arc(250, 250, 100, Math.PI * 24/30, Math.PI * 32/30); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.arc(250, 250, 100, Math.PI * 36/30, Math.PI * 44/30); 
     ctx.stroke(); 

     ctx.beginPath(); 
     ctx.arc(250, 250, 100, Math.PI * 48/30, Math.PI * 56/30); 
     ctx.stroke(); 
    } 
} 

draw(); 

而且這裏是你的提琴:http://jsfiddle.net/utWdM/13/

+0

起初,我嘗試過這樣的事情。它確實有效,但我覺得我錯過了一些重要的東西。最終,我意識到複雜的數學並不複雜,實際上非常有趣。 = D我將在未來一次又一次地使用知識。 – slacktracer

+1

還有別的。我明白了''closePath'在這裏沒有必要。它不是'endPath'。它沒有做我想象的那樣。一個寶貴的教訓。你可以在這個小提琴中看到它:http://jsfiddle.net/utWdM/7/。 – slacktracer

+1

closePath()將起點與終點連接起來,而不需要弧。另外,在stroke()之後調用它是沒有意義的,因爲stroke是柵格化(輪廓)路徑的方法。 – K3N

3

如果你想要一點靈活的解決方案,即。如果你想改變的段數,每個段的大小,那麼你可以創建一個通用的功能,像這樣:

/** 
* ctx  = context 
* x/y = center 
* radius = of circle 
* offset = rotation in angle (radians) 
* segments = How many segments circle should be in 
* size  = size of each segment (of one segment) [0.0, 1.0] 
*/ 
function dashedCircle(ctx, x, y, radius, offset, segments, size) { 

    var pi2 = 2 * Math.PI,    /// cache 2*Math.PI = 360 degrees in rads 
     segs = pi2/segments,   /// calc. size of each segment in rads 
     len = segs * size,    /// calc. length of segment in rads 
     i = 0, 
     ax, ay; 

    ctx.save(); 
    ctx.translate(x, y); 
    ctx.rotate(offset);    /// rotate canvas 
    ctx.translate(-x, -y); 

    for(; i < pi2; i += segs) { 
     ax = x + radius * Math.cos(i); /// calculate start position of arc 
     ay = y + radius * Math.sin(i); 
     ctx.moveTo(ax, ay);   /// make sure to move to beginning of arc 
     ctx.arc(x, y, radius, i, i + len); /// draw arc 
    } 

    ctx.restore();      /// remove rotation 
} 

然後在你的代碼,你只需撥打:

ctx.beginPath(); 

dashedCircle(ctx, 250, 250, 100, 0, 5, 0.7); 

ctx.lineWidth = 15; 
ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)'; 
ctx.stroke(); 
/// don't closePath here 

Modified fiddle here

使用偏移參數是一件輕而易舉的將它旋轉:

var offset = 0; 
var step = 0.03; 
var pi2 = 2 * Math.PI; 

(function loop() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.beginPath(); 

    dashedCircle(ctx, 250, 250, 100, offset % pi2, 5, 0.7); 
    ctx.stroke(); 

    offset += step; 

    requestAnimationFrame(loop); 
})(); 

Rotating circle fiddle

+1

哇!真棒!我正在研究你的小提琴以儘可能地理解它們。我已經學到了很多東西!起初,尺寸一點也不清楚。現在我看到它就像一個相對大小。真正需要繪製多少弧線。考慮到每個弧線是整個圓的一部分。這真的很聰明,這是我想要內化的那種洞察力。 – slacktracer

+1

現在我的需求是非常具體的,但仍然,我的代碼學到的東西是非常寶貴的。非常感謝你。 = D 我現在的目標已經實現!:http://anzol.biz/ – slacktracer

相關問題