【问题标题】:Clip an image to form an oval (centered image)裁剪图像以形成椭圆形(居中图像)
【发布时间】:2015-11-24 16:25:29
【问题描述】:

我正在尝试将图像剪辑成形状,然后在画布上绘制它们。我很好奇如何剪辑图像以将其返回为椭圆形。我会使用arc()bezierCurves() 之类的东西吗?

【问题讨论】:

    标签: javascript canvas shapes


    【解决方案1】:

    我认为最方便的方法是设置边界半径。

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

    如果你想用 javascript 来做,你应该使用:

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

    这也适用于图像。

    【讨论】:

    • 对不起,我想在画布上画它:P
    【解决方案2】:

    您需要创建一个椭圆形剪切路径。您可以用四条贝塞尔曲线近似椭圆。假设你想让椭圆适合一个矩形,曲线端点可以是矩形边的中点,曲线控制点可以是矩形边的中点和角的中间。矩形。

    例如,您可以将以下 HTML 代码用于画布元素...

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

    使用以下 JavaScript 代码使用大致椭圆形的剪切路径绘制图像...

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

    创建椭圆路径的另一种解决方案是使用 arc() 方法创建圆形路径,然后使用 scale() 方法将圆形路径转换为椭圆路径。

    【讨论】:

      【解决方案3】:

      您可以像这样通过缩放圆(圆 == 弧)来绘制椭圆:

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

      然后您可以使用合成来绘制图像,使其仅出现在椭圆形内部。

      这是通过context.globalCompositeOperation='source-atop' 完成的,这会导致新像素仅在与现有不透明像素重叠时才会出现:

      加入一点数学比率,你甚至可以得到椭圆来显示最大数量的图像...

      示例代码和演示:

      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; }
      &lt;canvas id="canvas" width=300 height=300&gt;&lt;/canvas&gt;

      【讨论】:

        猜你喜欢
        • 2014-05-01
        • 1970-01-01
        • 2011-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-21
        相关资源
        最近更新 更多