切割图像上的不规则形状

时间:2011-07-13 10:04:02

标签: javascript drawing shape html5-canvas

我正在尝试使用canvas clip()方法将图像剪切成特定的形状。

我已按照以下步骤执行此操作:

  1. 画一个矩形。
  2. 在每一边画半圆圈。右半圆和右半圆向外突出,左半圆和上半圆向内。
  3. 下面提供了代码段:

    var canvasNode = this.hasNode();
    var ctx = canvasNode && canvasNode.getContext('2d');
    
    var image = new Image();
    image.onload = function() {
      ctx.drawImage(image, 0, 0, 512, 384);
    };
    
    image.src = "images/image.png";
    var startX = 200;
    var startY = 0;
    
    var rectWidth = 150;
    var rectHeight = 150;
    var radius = 30;
    
    //Main Rect
    ctx.rect(startX, startY, rectWidth, rectHeight);
    
    //Right arc
    ctx.moveTo(startX+=rectWidth, startY+=(rectHeight/2));
    ctx.arc(startX, startY, radius, 3 * Math.PI / 2, Math.PI / 2, false);
    
    //Left arc
    ctx.moveTo(startX-=(rectWidth / 2), startY+=(rectHeight / 2));
    ctx.arc(startX, startY, radius, 0, Math.PI, true);
    
    ctx.moveTo(startX-=(rectWidth / 2), startY-=(rectWidth / 2));
    ctx.arc(startX, startY, radius, 3 * Math.PI / 2, Math.PI / 2, false);
    
    ctx.clip();
    

    我使用的图像尺寸为800 x 600(png)。请帮助我理解我在这里做错了什么。

1 个答案:

答案 0 :(得分:2)

首先,你为什么要使用clip?您目前只是绘制半圆,没有clip

其次,您正在创建路径和剪辑,但是您从不抚摸路径。因此,您不会在屏幕上看到任何内容。

如果您只是笔划而不是剪辑,它对我来说部分起作用:http://jsfiddle.net/r6yAN/。你没有包括顶部的半圆。

编辑:好像你没有使用最好的裁剪方法。你绘制一个矩形,但这也包括半圆形的一条线。如果你自己绘制每条线/弧,你会更好:http://jsfiddle.net/CH6qB/6/

主要思想是如图所示从点到点移动:

image

首先从(startX, startY)开始,然后从(startX + lineWidth, startY)开始,然后在(startX + rectWidth / 2, startY)pi0(逆时针)等处的弧线等。

如果您想在绘制图像后对路径进行描边,则最好再次取消剪辑。否则,中风的质量不会很好。

var canvasNode = document.getElementById('cv');
var ctx = canvasNode && canvasNode.getContext('2d');

var image = new Image();
image.onload = function() {
    // draw the image, region has been clipped
    ctx.drawImage(image, startX, startY);

    // restore so that a stroke is not affected by clip
    // (restore removes the clipping because we saved the path without clip below)
    ctx.restore();
    ctx.stroke();
};

image.src = "http://www.lorempixum.com/200/200/";

var startX = 200;
var startY = 0;

var rectWidth = 150;
var rectHeight = 150;
var radius = 30;

var lineWidth  = rectWidth  / 2 - radius;
var lineHeight = rectHeight / 2 - radius;

// typing pi is easier than Math.PI each time
var pi = Math.PI;

ctx.moveTo(startX, startY);

ctx.lineTo(startX + lineWidth, startY);
ctx.arc(startX + rectWidth / 2, startY,
        radius,
        pi, 0, true);
ctx.lineTo(startX + rectWidth, startY);

ctx.lineTo(startX + rectWidth, startY + lineHeight);
ctx.arc(startX + rectWidth, startY + rectHeight / 2,
        radius,
        -pi / 2, pi / 2, false);
ctx.lineTo(startX + rectWidth, startY + rectHeight);

ctx.lineTo(startX + rectWidth - lineWidth, startY + rectHeight);
ctx.arc(startX + rectWidth / 2, startY + rectHeight,
        radius,
        0, pi, false);
ctx.lineTo(startX, startY + rectHeight);

ctx.lineTo(startX, startY + rectHeight - lineHeight);
ctx.arc(startX, startY + rectHeight / 2,
        radius,
        pi/2, pi*3/2, true);
ctx.lineTo(startX, startY);

ctx.save(); // Save the current state without clip

ctx.clip();