2012-10-11 16 views
11

細い線で始まり、終わりまで気分的に広がる線を描こうとしています。私は半滑らかな曲線(いくつかの直線から合成)を描く必要があり、私はこの課題を解決する方法を見つけるのに問題があります。HTMLキャンバスで線幅が連続的に変化する線を描く

このバイオリンは私の問題を示しています

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

あなたは脳卒中(呼び出すとき)、現在設定されている線幅は、行全体ストロークに使用されています。私の最初の考えは、個々の線画を個別に描くことでしたが、もちろん、コーナーの線には目立つ隙間が残っていました。

私の最高のオプションは何ですか?私はコーナーを正しく得るために多角形(台形)を描くことに頼るべきですか?

もっと簡単な方法はありますか?

(編集:私は実際に楕円または任意の他の基本的な図形を描画しようとしているわけではないことに注意してください。私は数学関数をプロットしようとしている、速度を表すために、線の太さを使用して)

+4

あなたの最良のオプションは、おそらく、代わりに 'stroke'の' bezierCurveTo'または 'quadraticCurveTo'と' fill'を使用しようとしている:これは素晴らしいソリューションであることが判明しましたそれは数学を複雑にしますが、望みの結果を得るには唯一の方法でしょう。私は、複数の省略記号を描き、各ステップをオフセット/縮小することで、同様の異なる効果を達成することができました:http://jsfiddle.net/Shmiddty/ZvuQG/3/ – Shmiddty

答えて

4

興味のある方は、私の問題を解決する2つの解決策を考え出しました。

最初のアイデアは、実際に各点をコーナーとして描き、キャンバスを使ってきれいな角度を描くことでした。デモで見ることができる。

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

これを解決するもう一つの方法は、それぞれのプロット点を速度で決まる半径の円とみなすことです。

これらの円のプロファイルエッジを結合するプロットパス(直線または曲線、選択したもの)、最初は上に、最後を丸め、下の開始点に戻します。最後にパスを記入してください。

これは、プロットポイントの「円」に近づくにつれて、伸び縮みが滑らかになるはずです。

関連する問題