J'essaie de découper des images en formes puis de les dessiner sur du canvas. Je suis curieux de savoir comment est-ce que je couperais une image pour la renvoyer comme une forme ovale. Est-ce que j'utiliserais quelque chose comme arc()
ou bezierCurves()
?Clip une image pour former un ovale (image centrée)
Répondre
Je crois que le moyen le plus pratique serait de définir le rayon de la frontière.
#hey{
background:red;
color:white;
padding:5px;
border-radius:5px;
}
<div id="hey">hey</div>
Si vous voulez le faire avec javascript, vous devez utiliser:
document.getElementById("hey").style.borderRadius="5px";
Cela fonctionne aussi avec des images.
Vous devez créer un tracé de détourage ovale. Vous pouvez approximer un ovale avec quatre courbes de Bézier. En supposant que vous voulez que l'ovale s'inscrive dans un rectangle, les extrémités de la courbe peuvent être les points médians des côtés du rectangle et les points de contrôle de la courbe peuvent être à mi-chemin entre les points médians des côtés du rectangle et les coins de le rectangle.
Par exemple, vous pouvez utiliser le code HTML suivant pour un élément de toile ...
<canvas id="myCanvas" width="300" height="250"></canvas>
avec le code JavaScript suivant pour dessiner une image en utilisant un masque à peu près ovale ...
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var r = { x: 50, y: 50, w: 200, h: 150 };
var imag = new Image();
imag.src = "images/koala.png";
imag.addEventListener("load", function() {
context.save();
context.beginPath();
context.moveTo(r.x + r.w, r.y + 0.5 * r.h);
context.bezierCurveTo(r.x + r.w, r.y + 0.25 * r.h, r.x + 0.75 * r.w, r.y, r.x + 0.5 * r.w, r.y);
context.bezierCurveTo(r.x + 0.25 * r.w, r.y, r.x, r.y + 0.25 * r.h, r.x, r.y + 0.5 * r.h);
context.bezierCurveTo(r.x, r.y + 0.75 * r.h, r.x + 0.25 * r.w, r.y + r.h, r.x + 0.5 * r.w, r.y + r.h);
context.bezierCurveTo(r.x + 0.75 * r.w, r.y + r.h, r.x + r.w, r.y + 0.75 * r.h, r.x + r.w, r.y + 0.5 * r.h);
context.closePath();
context.clip();
context.drawImage(imag, r.x, r.y, r.w, r.h);
context.restore();
});
Une solution alternative pour créer le chemin ovale consisterait à utiliser la méthode arc() pour créer un chemin circulaire, puis utiliser la méthode scale() pour transformer le chemin du cercle en un chemin ovale.
Vous pouvez dessiner un ovale en escaladant un cercle (cercle == arc) comme ceci:
// Make an oval that's twice as tall as its width
// and draw it at the center of the canvas
var scaleX=1;
var scaleY=2;
var radius=canvas.width;
ctx.scale(scaleX,scaleY);
ctx.arc(canvas.width/scaleX/2,canvas.height/scaleY/2,radius,0,Math.PI*2);
ctx.fill();
Ensuite, vous pouvez utiliser compositing pour dessiner l'image de sorte qu'il ne semble à l'intérieur de l'ovale.
Cela se fait avec context.globalCompositeOperation='source-atop'
qui provoque de nouveaux pixels apparaissent uniquement si elles se chevauchent pixels opaques existants:
Toss dans un peu de rapports mathématiques et vous pouvez même obtenir l'ovale afficher le montant maximum de l'image ...
Exemple de code et une démonstration:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/kidwallpaper.jpg";
function start(){
// resize the canvas to equal the image size
var iw=img.width;
var ih=img.height;
cw=canvas.width=iw;
ch=canvas.height=ih;
// calculate the scaling needed to max the display of the image
// inside the oval
if(iw>ih){
var scaleX=iw/ih
var scaleY=1;
var r=ih/2;
}else{
var scaleX=1;
var scaleY=ih/iw;
var r=iw/2;
}
// scale so the circle (arc) becomes an oval
ctx.scale(scaleX,scaleY);
ctx.arc(cw/scaleX/2,ch/scaleY/2,r,0,Math.PI*2);
ctx.fill();
// undo the scaling
ctx.scale(1/scaleX,1/scaleY);
// draw the image centered inside the oval using compositing
ctx.globalCompositeOperation='source-atop';
ctx.drawImage(img,cw/2-img.width/2,ch/2-img.height/2);
ctx.globalCompositeOperation='source-atop';
}
body{ background-color: black; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>
Désolé, je veux dessiner sur la toile: P – Theepicpowner