本文介绍了具有“羽毛”的帆布剪辑边缘效应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在将图片绘制到HTML5画布并使用圆弧屏蔽它,在绘制图片之前调用clip(),以便只显示圆弧中的部分。我怎么能羽化这条弧的边缘?我知道从googling,没有简单的方法来简单地应用羽毛绘制的画布。对于其边缘接触弧的图像的像素数据有什么抵触?非常感谢您的帮助。



以下是我的代码的相关部分:

  ctx.arc(canvas.width / 2,canvas.height / 2,250,0,6.28,false); //绘制圆形
ctx.restore
ctx.save();
ctx.drawImage(background,0,0,
background.width * scale,background.height * scale);
ctx.clip(); //调用剪辑方法,以便下一个渲染被剪辑在最后一个路径
ctx.drawImage(img,0,0,
img.width * scale,img .height * scale);
ctx.closePath();
ctx.restore();

UPDATE



感谢您的彻底回答和非常有用的代码/评论肯!我昨晚花了几个小时试图在我的特定用例中工作这个解决方案,我有麻烦。看来,如果我使用第二种画布技术剪辑一个图像,你描述我不能重绘它的转换方式,我可以用一个arc()和clip()例程。






I'm currently drawing an image to an HTML5 Canvas and masking it with an arc, calling clip() before I draw the image so that only the portion that's in the arc is shown. How can I feather the edges of this arc? I know from googling around that there is no simple way to simply apply a "feather" to a shape drawn with canvas. What abut going in on the pixel data for the image where its edges touch the arc? Thanks for any help.

Here is the relevant portion of my code:

ctx.arc(canvas.width/2, canvas.height/2, 250, 0, 6.28, false);//draw the circle
ctx.restore();
ctx.save();
ctx.drawImage(background, 0, 0,
              background.width * scale, background.height * scale);
ctx.clip();//call the clip method so the next render is clipped in last path
ctx.drawImage(img, 0, 0,
              img.width * scale, img.height * scale);
ctx.closePath();
ctx.restore();

UPDATE

Thanks for the thorough answer and very helpful code/comments Ken!! I spent a few hours last night trying to work this solution in my particular use case and I'm having trouble. It seems that if I clip an image with the second-canvas technique you describe I can't redraw it on transforms the same way that I can with an arc() and clip() routine. Here's a JS Fiddle of what I'm trying to accomplis, minus the feathering on the arc, notice the click and drag events on the two layered images.

http://jsfiddle.net/g3WkN/

I tried replacing the arc() with your method, but I'm having a hard time getting that to be responsive to the transforms that happen on mouse events.

解决方案

Technique

You can achieve this by combining the following steps:

  • Use off-screen canvas
  • Use the shadow feature (the secret ingredient)
  • Use composite modes

The concept is based on having the browser make the feather internally by utilizing the blurred shadow. This is much faster than blurring in JavaScript. As we can make shadow for any object you can make complex feathered masks.

The off-screen canvas is used to draw the shadow only. We achieve this by moving the actual shape outside the canvas and then offset the shadow accordingly. The result is that shadow is drawn on the off-screen canvas while the actual shape is "invisible".

Now that we have a feathered version of our shape we can use that as a mask for composite mode. We choose destination-out to cleat where the shadow is drawn, or destination-in to invert the mask.

Example

Lets create a wrapper function that do all the steps for us

ONLINE DEMO HERE

function clipArc(ctx, x, y, r, f) { /// context, x, y, radius, feather size

    /// create off-screen temporary canvas where we draw in the shadow
    var temp = document.createElement('canvas'),
        tx = temp.getContext('2d');

    temp.width = ctx.canvas.width;
    temp.height = ctx.canvas.height;

    /// offset the context so shape itself is drawn outside canvas
    tx.translate(-temp.width, 0);

    /// offset the shadow to compensate, draws shadow only on canvas
    tx.shadowOffsetX = temp.width;    
    tx.shadowOffsetY = 0;

    /// black so alpha gets solid
    tx.shadowColor = '#000';

    /// "feather"
    tx.shadowBlur = f;

    /// draw the arc, only the shadow will be inside the context
    tx.arc(x, y, r, 0, 2 * Math.PI);
    tx.closePath();
    tx.fill();

    /// now punch a hole in main canvas with the blurred shadow
    ctx.save();
    ctx.globalCompositeOperation = 'destination-out';
    ctx.drawImage(temp, 0, 0);
    ctx.restore();
}

That's all there is to it.

USAGE

clipArc(context, centerX, centerY, radius, featherSize);

With demo background (see fiddle):

ctx.fillStyle = '#ffa';
ctx.fillRect(0, 0, demo.width, demo.height);

clipArc(ctx, 200, 200, 150, 40);

Result:

If you want to keep center intact just replace composite mode with destination-in.

Demo for inverted feathered mask

这篇关于具有“羽毛”的帆布剪辑边缘效应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 17:42