用HTML5 Canvas 做擦除及扩散效果(3)

function CanvasFade(canvas){
    this.canvas=canvas;
    this.ctx=canvas.getContext("2d");
    this.width=canvas.width;
    this.height=canvas.height;
}

CanvasFade.prototype={
    draw:function(config){
        var _self=this;
        var cfg=config?config:{x:200,y:200,r:120};
        var ratio=cfg.r/2;
        var grd = _self.ctx.createRadialGradient(cfg.x, cfg.y, 0.000, cfg.x, cfg.y, cfg.r);
        grd.addColorStop(0.000, 'rgba(255, 0, 0, 0.900)');
        grd.addColorStop(0.5, 'rgba(255, 0, 0, 0.600)');
        grd.addColorStop(1.0, 'rgba(255, 0, 0, 0.000)');
        _self.ctx.fillStyle = grd;
        _self.ctx.arc(cfg.x, cfg.y, cfg.r,0,Math.PI*2,true);
        _self.ctx.fill();
    }
};
var canvasFade=new CanvasFade(Jquery('#theCanvas')[0]);
canvasFade.draw({x:100,y:200y,r:20r});

可以看出实现起来非常简单,这段代码是测试使用的,颜色值是红色,看起来就像热区图,要实现雾霾扩散,只需要更改颜色值即可,实际效果如下:

用HTML5 Canvas 做擦除及扩散效果

ps. 这里是多次调用了draw的最终效果。

硬骨头

 仅从视觉上看,这两个需求非常接近,因此很容易误以为目标就要实现了。程序开发的一大特点就是[There is more to it then meets the eyes]。那些看起来很炫酷的交互对于开发者可能非常容易实现,因为厂商可能在底层已经实现了。而那些看起来很简单的东西,可能需要花费更多的力气,这也常常成为产品人员和开发人员摩擦的一个原因。

  我们来分析需求,雾霾本身覆盖在地图上,并不是均匀的(当然也可以简化成均匀的,这里不是主要困难点),主要问题就是雾霾驱散之后显示出来的是没有雾霾覆盖的地图,而不是纯颜色(可以参看文末gif图片)。边缘的模糊效果就很难实现,因为在设置strokeStyle的时候,如果设置为渐变色,很容易实现边缘模糊,但是就只能用颜色值,如果把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();

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b9a55a09a87d38878c49650f5ef88052.html