2012-01-25 75 views

回答

0

我相當確定這取決於您使用的瀏覽器。最後我查了一下(前一陣子 - 可能已經改變了),Firefox和Chrome並沒有抗鋸齒邊緣,而IE9的確如此。

+0

我不是指antialiased邊緣,它隻影響薄外層像素。看看http://muro.deviantart.com/,他們如何實現這個非常柔和的邊緣幾個像素層? – Homan

7

三種可能的解決方案:

  1. 你可以寫你的線條到離屏畫布,應用模糊濾鏡,然後繪製結果爲可見的畫布。

  2. 如果您只使用直線段,則可以爲每個線段使用線性漸變。梯度的方向必須與線段的方向相比爲90°角

  3. 在同一位置多次繪製相同的線條先用全寬和低α值然後減小寬度並增加阿爾法

實施例使用的線性梯度爲每個線段:

http://jsfiddle.net/chdh/MmYAt/

function drawSoftLine(x1, y1, x2, y2, lineWidth, r, g, b, a) { 
    var lx = x2 - x1; 
    var ly = y2 - y1; 
    var lineLength = Math.sqrt(lx*lx + ly*ly); 
    var wy = lx/lineLength * lineWidth; 
    var wx = ly/lineLength * lineWidth; 
    var gradient = ctx.createLinearGradient(x1-wx/2, y1+wy/2, x1+wx/2, y1-wy/2); 
     // The gradient must be defined accross the line, 90° turned compared 
     // to the line direction. 
    gradient.addColorStop(0, "rgba("+r+","+g+","+b+",0)"); 
    gradient.addColorStop(0.43, "rgba("+r+","+g+","+b+","+a+")"); 
    gradient.addColorStop(0.57, "rgba("+r+","+g+","+b+","+a+")"); 
    gradient.addColorStop(1, "rgba("+r+","+g+","+b+",0)"); 
    ctx.save(); 
    ctx.beginPath(); 
    ctx.lineWidth = lineWidth; 
    ctx.strokeStyle = gradient; 
    ctx.moveTo(x1, y1); 
    ctx.lineTo(x2, y2); 
    ctx.stroke(); 
    ctx.restore(); } 

示例畫線多次,通過減小寬度和增加的α:

http://jsfiddle.net/chdh/RmtxL/

function drawSoftLine(x1, y1, x2, y2, lineWidth, r, g, b, a) { 
    ctx.save(); 
    var widths = [1 , 0.8 , 0.6 , 0.4 , 0.2 ]; 
    var alphas = [0.2 , 0.4 , 0.6 , 0.8 , 1 ]; 
    var previousAlpha = 0; 
    for (var pass = 0; pass < widths.length; pass++) { 
     ctx.beginPath(); 
     ctx.lineWidth = lineWidth * widths[pass]; 
     var alpha = a * alphas[pass]; 
     // Formula: (1 - alpha) = (1 - deltaAlpha) * (1 - previousAlpha) 
     var deltaAlpha = 1 - (1 - alpha)/(1 - previousAlpha) 
     ctx.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + deltaAlpha + ")"; 
     ctx.moveTo(x1, y1); 
     ctx.lineTo(x2, y2); 
     ctx.stroke(); 
     previousAlpha = alpha; } 
    ctx.restore(); } 
+0

我創建了一個jsperf測試來比較這兩個選擇的性能:http://jsperf.com/feathered-canvas-line。看起來畫多行比較快,但我認爲它看起來很醜。 –

0

可以使用CSS濾波器模糊畫布上。這可能與SVG rasterization trick。你可以這樣做:

  1. 製作兩個畫布,一個在另一個之上。其中一個讓我們稱之爲«目標»和另一個«緩衝區»。緩衝區是你所畫的,Target是最終的畫布。

  2. css-filter: blur(px)應用於緩衝區畫布,以便用戶可以即時看到模糊預覽。

  3. 這是一個有趣的部分。在每個筆畫上(即在mouseup上),柵格化緩衝區畫布,將圖像放入<svg><foreignObject></foreignObject></svg>,對其應用相同的CSS濾鏡,柵格化SVG,並將柵格化的SVG放置在目標畫布上。這裏是gist with code example