2016-04-14 12 views
3

Gibt es eine Möglichkeit, die Schnittmaskenpfade in Leinwand zu glätten? Ich finde anscheinend eine Lösung online. Es ist ziemlich glatt in Firefox, aber nicht in Chrome oder Safari. Hier ist der Beispielcode und ein Link zu Codepen:Leinwandausschnitt ist nicht glatt

http://codepen.io/VincentPeters/pen/LNdZba?editors=0010

var canvas = document.getElementById('game'); 
var img; 
var circleSize = 100; 
var imageLoaded = false; 

$(document).ready(function() { 
    //circles in percentage 
    var circles = [ 
     [85, 75], 
     [25, 65], 
     [75, 40], 
     [30, 30] 
    ]; 

    var ctx = initCanvas(); 

    circles = calculateCirclePositions(ctx, circles); 

    img.onload = function() { 
     imageLoaded = true; 
     drawCircles(ctx, circles); 
     drawConnection(ctx, circles); 
    }; 
}); 

function calculateCirclePositions(ctx, circles) { 
    for (var i = 0; i < circles.length; i++) { 
     circles[i][0] = (circles[i][0]/100) * ctx.canvas.width; 
     circles[i][1] = (circles[i][1]/100) * ctx.canvas.height; 
    } 

    return circles; 
} 

function initCanvas() { 
    var ctx = canvas.getContext('2d'); 
    ctx.imageSmoothingEnabled = true; 

    ctx.canvas.width = 600; 
    ctx.canvas.height = 600; 

    img = new Image(); 
    imageLoaded = false; 
    img.src = 'http://i.imgur.com/jDp7UPB.jpg'; 

    return ctx; 
} 

function drawCircles(ctx, circles) { 
    if (!imageLoaded) { 
     return; 
    } 

    circles.forEach(function (entry) { 
     drawCircle(ctx, entry[0], entry[1]) 
    }); 
} 

function drawCircle(ctx, x, y) { 
    if (!imageLoaded) { 
     return; 
    } 

    ctx.save(); 
    ctx.beginPath(); 
    ctx.arc(x, y, circleSize/2, 0, 2 * Math.PI); 
    ctx.closePath(); 
    ctx.clip(); 
    ctx.drawImage(img, 0, 0); 
    ctx.restore(); 
} 

function drawConnection(ctx, circles) { 
    for (var i = 0; i < circles.length - 1; i++) { 
     var V = []; 
     var N = []; 
     var R1 = []; 
     var R2 = []; 
     var R3 = []; 
     var R4 = []; 

     V[0] = circles[i + 1][0] - circles[i][0]; 
     V[1] = circles[i + 1][1] - circles[i][1]; 

     var length = Math.sqrt(V[1] * V[1] + -V[0] * -V[0]); 

     N[0] = V[1]/length; 
     N[1] = -V[0]/length; 

     R1 = [ 
      circles[i][0] + N[0] * circleSize/2, 
      circles[i][1] + N[1] * circleSize/2]; 

     R2 = [circles[i][0] - N[0] * circleSize/2, 
      circles[i][1] - N[1] * circleSize/2]; 

     R3 = [circles[i + 1][0] + N[0] * circleSize/2, 
      circles[i + 1][1] + N[1] * circleSize/2]; 

     R4 = [circles[i + 1][0] - N[0] * circleSize/2, 
      circles[i + 1][1] - N[1] * circleSize/2]; 

     ctx.save(); 
     ctx.moveTo(R1[0], R1[1]); 
     ctx.lineTo(R2[0], R2[1]); 
     ctx.lineTo(R4[0], R4[1]); 
     ctx.lineTo(R3[0], R3[1]); 
     ctx.lineTo(R1[0], R1[1]); 

     ctx.clip(); 
     ctx.closePath(); 
     ctx.drawImage(img, 0, 0); 

     ctx.restore(); 
    } 
} 
+0

vielleicht jemand wird eine bessere Lösung und eine Erklärung haben, aber es scheint, dass die Verwendung von 'globalCompositeOperation' und eine Offscreen-Leinwand bessere Ergebnisse bietet: http://codepen.io/anon/pen/YqaeGL?editors=0010 – Kaiido

+0

zeichne es zweimal als groß und herunterskaliert zusammen mit @Kaiidos Lösung: D – Unispaw

Antwort

1

Sie könnten Ihre Leinwand doppelt so groß und verkleinern sie machen nach unten. Es wird weniger leistungsfähig sein, aber die Qualität wird besser sein.

Verwandte Themen