Clip an image to form an oval (centered image)

风格不统一 提交于 2019-12-13 04:26:13

问题


I am trying to clip images into shapes and then draw them on canvas. I am curious how would I clip an image to return it as an oval shape. Would I use something like arc() or bezierCurves()?


回答1:


I believe the most convenient way would be to set the border radius.

#hey{
  background:red;
  color:white;
  padding:5px;
  border-radius:5px; 
}
<div id="hey">hey</div>

If you want to do it with javascript, you should use:

document.getElementById("hey").style.borderRadius="5px";

This also works with images.




回答2:


You will need to create a oval clipping path. You can approximate an oval with four Bezier curves. Assuming that you want the oval to fit inside a rectangle, the curve end points can be the mid points of the sides of the rectangle and the curve control points can be half way between the mid points of the sides of the rectangle and the corners of the rectangle.

For example, you could use the following HTML code for a canvas element...

<canvas id="myCanvas" width="300" height="250"></canvas>

with the following JavaScript code to draw an image using a roughly oval clipping path...

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

An alternative solution for creating the oval path, would be to use arc() method to create a circle path and then use scale() method to transform the circle path into an oval path.




回答3:


You can draw an oval by scaling a circle (circle == arc) like this:

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

Then you can use compositing to draw the image so it only appears inside the oval.

This is done with context.globalCompositeOperation='source-atop' which causes new pixels to appear only if they overlap existing opaque pixels:

Toss in a little bit of math ratios and you can even get the oval to display the maximum amount of image...

Example code and a Demo:

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>


来源:https://stackoverflow.com/questions/33898822/clip-an-image-to-form-an-oval-centered-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!