把strokeStyle设置为pattern就可以使用图片,可是这时就没法设置渐变了,边缘就是整齐切割的,无法满足需求,在反复尝试和求助google之后,终于在stackoverflow上找到了一点线索,貌似有个外国哥们也撞上了类似的需求,不过他非常聪明地绕过了strokeStyle这个问题,所以最终的实现方案就是受到他的启发而实现的,并非由我原创的。
先看代码:
function clipArc(ctx, x, y, r, f) {
? ? var temp = document.createElement('canvas'),
? ? ? ? tx = temp.getContext('2d');
? ? temp.width = ctx.canvas.width;
? ? temp.height = ctx.canvas.height;
? ? tx.translate(-temp.width, 0);
? ? tx.shadowOffsetX = temp.width;? ?
? ? tx.shadowOffsetY = 0;
? ? tx.shadowColor = '#000';
? ? tx.shadowBlur = f;
? ? tx.arc(x, y, r, 0, 2 * Math.PI);
? ? tx.closePath();
? ? tx.fill();
? ? ctx.save();
? ? ctx.globalCompositeOperation = 'destination-in';
? ? ctx.drawImage(temp, 0, 0);
? ? ctx.restore();
}
function CanvasFade(canvas){
? ? this.canvas=canvas;
? ? this.ctx=canvas.getContext("2d");
? ? this.imgSrc=canvas.getAttribute("imgSrc");
? ? this.width=canvas.width;
? ? this.height=canvas.height;
}
CanvasFade.prototype={
? ? init:function(config){
? ? ? ? var _self=this;
? ? ? ? var cfg=config?config:{x:100,y:100,r:120,f:40};
? ? ? ? var img=new Image();
? ? ? ? img.onload=function(){
? ? ? ? ? ? var pat=_self.ctx.createPattern(img,"no-repeat");
? ? ? ? ? ? _self.ctx.fillStyle=pat;
? ? ? ? ? ? _self.ctx.fillRect(0, 0, _self.width, _self.height);
? ? ? ? ? ? clipArc(_self.ctx, cfg.x, cfg.y, cfg.r, cfg.f);
? ? ? ? };
? ? ? ? img.src=this.imgSrc;
? ? }
};
var c=document.querySelector('#theCanvas');
var cf=new CanvasFade(c);
cf.init();
这里的秘密武器就是利用了shadow,即阴影,在canvas里边绘制图形的时候,可以给图形添加阴影,而阴影可以有边缘模糊的效果。这里在实际绘制的时候,先创建了一个过渡canvas(这个canvas本身并不绘制图形,主要起模糊剪切的作用),将这个canvas向左平移了一个宽度,这样它就移出了当前canvas的可视范围,然而精妙之处在于它上下文的shadowOffsetX设置为了向右一个宽度,这样其内部任何图形的阴影刚好又落在了当前canvas的正确位置,这里设置了它的阴影颜色为黑色,但是有一定的羽化效果(tx.shadowBlur = f),另一个秘密武器就是globalCompositeOperation,这个属性用来设定如何将一个源(新的)图像绘制到目标(已有的)的图像上,其详细信息可以参考http://www.html5canvastutorials.com/advanced/html5-canvas-global-composite-operations-tutorial/ ,实际效果如下图:

可以看出实际效果还是非常不错的。并且动画的形式可以是更多样的,而且这种形式也可以有更多的变种,以满足更广泛的需求。
至此,利用canvas制作擦除和扩散效果的方法介绍完毕了。欢迎批评指正^_^
--------------------------------------分割线 --------------------------------------?
--------------------------------------分割线 --------------------------------------