2010-11-25 11 views
25

Comment puis-je dessiner une image dans un cercle? Si oui:Toile HTML5 - Remplir un cercle avec l'image

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

Comment puis-je utiliser fill() pour le remplir avec mon image dessinée?

Répondre

46

Je l'ai ceci l'autre jour pour une grande chose que je fais;

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

Travaillé parfait pour moi.

est ici une version plus complexe de ce que je fait qui ne cache d'image aussi, https://jsfiddle.net/jaredwilli/ex5n5/

+0

Ça a l'air génial, va certainement essayer! – tbleckert

+1

Tandis que c'était finalement ce que j'avais trouvé comme solution dans la toile, après l'avoir augmentée et modifiée avec toutes sortes de choses qui devaient être faites pour l'application sur laquelle j'ai travaillé, il s'est avéré que 2 jours avant le lancement et a eu 2 jours pour faire une solution alternative qui s'est avérée être de loin beaucoup mieux et plus cross-navigateur pour les deux ordinateurs de bureau et mobiles. La solution était la réponse @MatTheCat suggérée "En utilisant un avec CSS pour border-radius". Bordure-rayon juste utilisé: 100% pour le rendre circulaire. La meilleure solution est de loin la meilleure. Just sayin ... – jaredwilli

+0

Je voulais juste ajouter, que c'est la meilleure pratique pour définir le src * après * la configuration du rappel 'onload'. C'est à dire. 'thumbImg.src = 'path_to_image';' devient la dernière ligne –

3

Pensez à utiliser certaines de ces alternatives:

  • L'utilisation d'un <img> avec CSS pour border-radius: http://jsfiddle.net/ChrisMorgan/BQGxA/

  • Utiliser SVG plutôt que <canvas> et définissez l'ellipse comme le chemin de détourage pour une image. (Chemins de détourage plus complexes sont alors faciles, trop)

Ne pas savoir plus sur vos besoins et de la situation, je ne sais pas si ceux-ci répondront à vos besoins, mais je pense qu'ils valent tout en tenant compte. <canvas> n'est pas la solution à tous vos problèmes - pour beaucoup de ces cas, CSS en HMTL normal et/ou SVG peut être une meilleure correspondance.

+0

SVG pourrait être le chemin à parcourir. Ce que je fais est, j'ai une vidéo et quand je fais une pause, une loupe apparaît. Ensuite, avec une toile, je dessine l'image de la vidéo sur la toile et je la zoome. Le problème est que la loupe est ronde, donc j'ai besoin de la découper ou de la remplir d'un arc. – tbleckert

+1

Dans ce cas, vous pourriez être intéressé par un article de Tutorialzine de juin, [http://tutorialzine.com/2010/06/apple-like-retina-effect-jquery-css/](Apple-like Retina Effect Avec jQuery). Cela couvre un effet de travail comme ça, mais avec une image statique plutôt qu'avec un cadre '

+0

J'ai fini par avoir besoin d'utiliser CSS border-radius comme alternative à la réponse que j'ai postée ci-dessus qui a été marquée comme la réponse acceptée dans le projet sur lequel j'ai travaillé pour l'application olympique Olympic Genome Project de Samsung.Il s'est avéré être la meilleure solution pour faire ce que nous avions besoin de faire pour que la version récente de Chrome 18 ne gâche pas complètement les performances de l'application, puisqu'ils ont rendu l'accélération matérielle 2D Canvas activée par défaut dans cette version, qui avait un bug que, pour une raison ou une autre, le dessin de grandes quantités de chemins complexes et d'images était extrêmement lent. – jaredwilli

9

Je ne sais pas si vous êtes à la recherche toujours la réponse, mais voici comment:

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"; 

Vous pouvez aussi le faire avec motif, mais vous obtenez moins de souplesse de positionnement de l'image

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

Le problème avec la méthode clip() est que Chrome va rendre les frontières non anticrénelage, comme le montre this question.

Une solution consiste à utiliser globalCompositeOperation comme indiqué dans la réponse de Daniel: « Comment puis-je puis utiliser fill() pour le remplir avec mon image dessinée »

//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, ...);