2010-11-25 17 views
25

Wie kann ich ein Bild in einem Kreis zeichnen? Wenn ich das tue:HTML5 Canvas - Fill Kreis mit Bild

context.beginPath(); 
context.arc((e.pageX),(e.pageY),161,0,Math.PI*2,true); 
context.closePath(); 

Wie kann ich dann fill() verwenden, um es mit meinem gezeichneten Bild zu füllen?

Antwort

46

Ich habe das ist neulich für eine große Sache, die ich mache;

var thumbImg = document.createElement('img'); 

thumbImg.src = 'path_to_image'; 
thumbImg.onload = function() { 
    tmpCtx.save(); 
    tmpCtx.beginPath(); 
    tmpCtx.arc(25, 25, 25, 0, Math.PI * 2, true); 
    tmpCtx.closePath(); 
    tmpCtx.clip(); 

    tmpCtx.drawImage(thumbImg, 0, 0, 50, 50); 

    tmpCtx.beginPath(); 
    tmpCtx.arc(0, 0, 25, 0, Math.PI * 2, true); 
    tmpCtx.clip(); 
    tmpCtx.closePath(); 
    tmpCtx.restore(); 
}; 

Arbeitete perfekt für mich.

Hier ist eine komplexere Version davon, die ich gemacht, das tut Bildcachierens auch https://jsfiddle.net/jaredwilli/ex5n5/

+0

Sieht gut aus, werde es definitiv versuchen! – tbleckert

+1

Obwohl dies letztlich das war, was ich als Lösung in Canvas gefunden hatte, nachdem ich es mit allen möglichen Dingen, die für die App erledigt werden mussten, stark vergrößert und modifiziert hatte, stellte sich heraus, dass 2 Tage vor dem Start etwas kam und hatte zwei Tage Zeit, um eine alternative Lösung zu finden, die viel schneller und browserübergreifender für Desktop und Mobile war. Die Lösung war die Antwort @MatTheCat vorgeschlagen "Verwenden Sie eine mit CSS für Border-Radius". Nur Rand-Radius verwendet: 100%, um es kreisförmig zu machen. Beste Lösung bei weitem. Just sayin ... – jaredwilli

+0

Ich wollte nur hinzufügen, dass es die beste Vorgehensweise ist, die src * nach * Einstellung des 'onload' Callbacks zu setzen. I.e. 'thumbImg.src = 'path_to_image';' wird zur letzten Zeile –

3

Betrachten wir einige dieser Alternativen erfüllen:

  • eine <img> mit CSS Verwendung für border-radius: für ein Bild http://jsfiddle.net/ChrisMorgan/BQGxA/

  • Verwendung SVG statt <canvas> und stellen Sie die Ellipse als Beschneidungspfad. (Komplexere Beschneidungspfade sind dann einfach auch)

nicht mehr über Ihre Anforderungen und Situation zu wissen, ich weiß nicht, ob diese Ihre Anforderungen gerecht werden, aber ich denke, dass sie unter Berücksichtigung wert sind. <canvas> ist nicht die Lösung für alle Ihre Probleme - für viele dieser Fälle kann CSS in normalen HMTL und/oder SVG eine bessere Übereinstimmung sein.

+0

SVG könnte der Weg sein zu gehen. Was ich mache ist, ich habe ein Video und wenn ich es pausiere, erscheint eine Lupe. Dann zeichne ich mit Leinwand das Bild des Videos auf die Leinwand und zoome es. Das Problem ist, dass die Lupe rund ist, also muss ich sie entweder abschneiden oder einen Bogen damit füllen. – tbleckert

+1

In diesem Fall könnten Sie interessiert sein, einen Tutorialzine Artikel von Juni zu betrachten, http://tutorialzine.com/2010/06/apple-like-retina-effect-jquery-css/](Apple-like Retina Effect Mit jQuery). Es behandelt einen solchen Arbeitseffekt, allerdings mit einem statischen Bild anstelle eines '

+0

Eigentlich musste ich CSS border-radius als Alternative zu der oben geposteten Antwort verwenden, die in dem Projekt, an dem ich für die Facebook-App für das Olympic Genome Project von Samsung gearbeitet habe, als akzeptierte Antwort markiert wurde.Es erwies sich als die beste Lösung für das, was wir tun mussten, damit die kürzlich veröffentlichte Version von Chrome 18 die Leistung der App nicht vollständig ruinierte, da sie die 2D Canvas-Hardwarebeschleunigung standardmäßig in der Version mit einem Fehler aktiviert hat Das machte aus irgendeinem Grund das Zeichnen großer Mengen komplexer Pfade und Bilder extrem langsam. – jaredwilli

9

Nicht sicher, ob Sie noch nach der Antwort suchen, aber hier ist, wie:

var ctx = document.getElementById('your_canvas').getContext("2d"); 
//ctx.lineWidth = 13; 
//ctx.strokeStyle = 'rgba(0,0,0,1)'; 
//ctx.fillStyle="rgba(0,0,0,0)" // if using this, make sure alpha < 1 

ctx.arc(100,100, 50, 0, Math.PI*2,true); // you can use any shape 
ctx.clip(); 

var img = new Image(); 
img.addEventListener('load', function(e) { 
    ctx.drawImage(this, 0, 0, 200, 300); 
    //ctx.fill(); 
//ctx.stroke(); 
}, true); 
img.src="/path/to/image.jpg"; 

Sie können dies auch mit Mustern tun, aber Sie bekommen weniger Bildplatzierung Flexibilität

ctx.arc(100,100, 70, 0, Math.PI*2,true); 
ctx.clip(); 

img = new Image() 
img.addEventListener('load', function(e) { 
    ctx.fillStyle = ctx.createPattern(this, 'no-repeat') 
    ctx.fill(); 
}, true); 
img.src="/path/to/image.jpg" 
2

Das Problem mit dem Clip() Methode ist, dass Chrome die Grenzen nicht antialiased machen, wie in this question gezeigt.

Eine Lösung ist global zu verwenden, wie in Daniels Antwort gezeigt: „Wie kann ich fülle dann() es mit meinem gezeichneten Bild zu füllen“

//set-up - probably only needs to be done once 
var scratchCanvas = document.createElement('canvas'); 
scratchCanvas.width = 100; 
scratchCanvas.height = 100; 
var scratchCtx = scratchCanvas.getContext('2d'); 


//drawing code 
scratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height); 

scratchCtx.globalCompositeOperation = 'source-over'; //default 

//Do whatever drawing you want. In your case, draw your image. 
scratchCtx.drawImage(imageToCrop, ...); 


//As long as we can represent our clipping region as a single path, 
//we can perform our clipping by using a non-default composite operation. 
//You can think of destination-in as "write alpha". It will not touch 
//the color channel of the canvas, but will replace the alpha channel. 
//(Actually, it will multiply the already drawn alpha with the alpha 
//currently being drawn - meaning that things look good where two anti- 
//aliased pixels overlap.) 
// 
//If you can't represent the clipping region as a single path, you can 
//always draw your clip shape into yet another scratch canvas. 

scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity 
scratchCtx.globalCompositeOperation = 'destination-in'; 
scratchCtx.beginPath(); 
scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true); 
scratchCtx.closePath(); 
scratchCtx.fill(); 


//Now that we have a nice, cropped image, we can draw it in our 
//actual canvas. We can even draw it over top existing pixels, and 
//everything will look great! 

ctx.drawImage(scratchCanves, ...);