2012-01-25 13 views

Odpowiedz

0

Jestem prawie pewien, że zależy to od przeglądarki, z której korzystasz. Ostatni sprawdziłem (jakiś czas temu - mogło się zmienić) Firefox i Chrome nie mają krawędzi antialias, podczas gdy IE9 to robi.

+0

Nie mówię tu o krawędziach antyaliasowanych, które działają tylko na cienką zewnętrzną warstwę pikseli. Spójrz na http://muro.deviantart.com/, w jaki sposób uzyskują one bardzo miękką krawędź o głębokości kilku pikseli? – Homan

7

trzy możliwe rozwiązania:

  1. można napisać swoje linie na płótnie off-screen, zastosować filtr rozmycia, a następnie wyciągnąć wynik do widzialnej płótnie.

  2. Jeśli używasz tylko segmentów prostych, możesz użyć liniowego gradientu dla każdego segmentu linii. Kierunek gradientu musi być pod kątem 90 stopni w stosunku do kierunku odcinka linii

  3. Narysuj te same linie wiele razy w tym samym miejscu, najpierw z pełną szerokością i niskim poziomem alfa. szerokość i zwiększania poziomu alfa

przykład za pomocą liniowego gradientu do każdego odcinka linii.

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(); } 

Przykład rysując linię wielokrotnie, poprzez zmniejszanie szerokości i zwiększenie alpha:

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

Stworzyłem test jsperf, aby porównać wydajność tych dwóch opcji: http://jsperf.com/feathered-canvas-line. Wygląda na to, że rysowanie wielu linii jest nieco szybsze, ale myślę, że wygląda o wiele brzydiej. –

0

można wykorzystywać filtr css rozmycie plandeki. Jest to możliwe z SVG rasterization trick. Oto, jak to zrobić:

  1. Wykonaj dwa płótna, jeden na drugim. Jeden z nich nazwijmy «Cel» i inny «Bufor». Bufor to taki, na którym rysujesz, a obiekt docelowy to wynikowe płótno.

  2. Zastosuj css-filter: blur(px) do płótna bufora, aby użytkownik mógł od razu zobaczyć zamazany podgląd.

  3. To jest interesująca część. Przy każdym obrysie (na przykład po kliknięciu myszą) rasteryzuj płótno bufora, umieść obraz w <svg><foreignObject></foreignObject></svg>, zastosuj do niego ten sam filtr CSS, zrób rasteryzację SVG i umieść zrasteryzowany SVG w kanwie docelowej. Oto gist with code example.

Powiązane problemy