2012-10-11 70 views
11

我試圖畫出一條線條,該線條以細線開始,然後逐漸變寬直至結束。我需要繪製半光滑的曲線(由幾條直線組成的複合曲線),並且在找到解決此任務的方法時遇到問題。在HTML畫布上以不斷變化的線條寬度繪製線條

這撥弄顯示我的問題:

http://jsfiddle.net/ZvuQG/1/

當你調用stroke(),當前設置的線寬用於中風的整條生產線。我的第一個想法是單獨畫出每一行,但當然這會在角落處留下明顯的空白。

這裏我最好的選擇是什麼?我是否應該採用繪製多邊形(梯形)來獲得正確的角?

有沒有更簡單的方法?

(編輯:請注意,我不是要實際繪製橢圓形或任何其他基本形狀,我想繪製數學函數,利用線條的粗細代表速度)

+4

你最好的選擇可能是將要使用'bezierCurveTo'或'quadraticCurveTo'和'fill',而不是'stroke',它會使數學複雜化,但它可能是獲得理想結果的唯一方法。我已經能夠通過繪製多個省略號和每一步抵消/縮小它們來實現類似但不同的效果:http://jsfiddle.net/Shmiddty/ZvuQG/3/ – Shmiddty

回答

4

對於那些有興趣的人,我提出了兩個解決我的問題。

第一個想法是將每個點實際繪製爲一個角,使用畫布繪製一個整齊的角度。的演示可以看出:

http://jsfiddle.net/7BkyK/2/

var ctx = document.getElementById('canvas1').getContext('2d'); 
var points = [null, null, null]; 

for(var i=0; i<24; i++) 
{ 
    var width = 0.5 + i/2; 

    var m = 200; 

    var x = Math.cos(i/4) * 180; 
    var y = Math.sin(i/4) * 140; 

    points[0] = points[1]; 
    points[1] = points[2]; 
    points[2] = { X:x, Y:y}; 

    if(points[0] == null) 
     continue; 

    var px0 = (points[0].X + points[1].X)/2; 
    var py0 = (points[0].Y + points[1].Y)/2; 

    var px1 = (points[1].X + points[2].X)/2; 
    var py1 = (points[1].Y + points[2].Y)/2; 

    ctx.beginPath(); 
    ctx.lineWidth = width; 
    ctx.strokeStyle = "rgba(0,0,0,0.5)"; 
    ctx.moveTo(m+px0,m+py0); 
    ctx.lineTo(m+points[1].X,m+points[1].Y); 
    ctx.lineTo(m+px1,m+py1); 
    ctx.stroke(); 
} 
​ 

第二和更漂亮的解決方案,通過Shmiddty的建議,是貝塞爾曲線使用。事實證明,這是一個很好的解決方案:

http://jsfiddle.net/Ssrv9/1/

// 1. 
// Varying line width, stroking each piece of line separately 
var ctx = document.getElementById('canvas1').getContext('2d'); 
var points = [null, null, null, null]; 

for(var i=-1; i<25; i = i +1) 
{ 
    var width = 0.5 + i/2; 

    var m = 200; 


    var x = Math.cos(i/4) * 180; 
    var y = Math.sin(i/4) * 140; 

    points[0] = points[1]; 
    points[1] = points[2]; 
    points[2] = { X:x, Y:y}; 

    if(points[0] == null) 
     continue; 


    var p0 = points[0]; 
    var p1 = points[1]; 
    var p2 = points[2]; 

    var x0 = (p0.X + p1.X)/2; 
    var y0 = (p0.Y + p1.Y)/2; 

    var x1 = (p1.X + p2.X)/2; 
    var y1 = (p1.Y + p2.Y)/2; 

    ctx.beginPath(); 
    ctx.lineWidth = width; 
    ctx.strokeStyle = "black"; 

    ctx.moveTo(m+x0, m+y0); 
    ctx.quadraticCurveTo(m+p1.X, m+p1.Y, m+x1, m+y1); 
    ctx.stroke(); 
} 

2

添加圓角線帽和二次曲線使整個事物看起來更加整齊。

例如參見here

+0

這是一個很好的解決方案,應該已經工作了,根據到我在問題中指定的參數。但是,我沒有說我想控制線條的不透明度,在這種情況下,圓角看起來不那麼好: http://jsfiddle.net/X2Vm7/ – Valdemar

0

解決這個問題的另一種方法是將每個繪圖點考慮爲由速度確定的半徑的圓。

繪製路徑連接這些圓的輪廓邊緣(直線或曲線,您的選擇),首先在頂部,圓形的最後一個,然後回到底部的起點。然後在最後填寫路徑。

這應該會給你一個平滑的線條擴大和縮小,因爲它接近你繪製點'圓'。