欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

canvas 绘制刮刮卡

程序员文章站 2023-10-30 12:54:28
思路=》 用div来展示刮奖结果,用canvas绘制刮奖前展示的图片或者文字;将canvas叠在div上方,刮奖是只需要操作canvas配合touch事件即可简单完成。 canvas刮奖可以用globalCompositeOperation属性制作。 globalCompositeOperation ......

思路=》

 用div来展示刮奖结果,用canvas绘制刮奖前展示的图片或者文字;将canvas叠在div上方,刮奖是只需要操作canvas配合touch事件即可简单完成。

 canvas刮奖可以用globalcompositeoperation属性制作。

 globalcompositeoperation:

属性值 描述
source-over (default) 新图形会覆盖在原有内容之上
destination-over 会在原有内容之下绘制新图形
source-in 新图形会仅仅出现与原有内容重叠的部分。其它区域都变成透明的
destination-in 原有内容中与新图形重叠的部分会被保留,其它区域都变成透明的
source-out 结果是只有新图形中与原有内容不重叠的部分会被绘制出来
destination-out 原有内容中与新图形不重叠的部分会被保留
source-atop 新图形中与原有内容重叠的部分会被绘制,并覆盖于原有内容之上
destination-atop 原有内容中与新内容重叠的部分会被保留,并会在原有内容之下绘制新图形
lighter 两图形中重叠部分作加色处理
darker 两图形中重叠的部分作减色处理
xor 重叠的部分会变成透明
copy 只有新图形会被保留,其它都被清除掉

实现代码
class scratch{
    constructor(options){
        this.obj = document.queryselector(options.obj);    //div容器
        this.bgpic = options.bgpic;    //刮刮卡前景图
        this.radius = options.radius;    //圆半径
        this.area = options.area || 50;    //擦拭部分面积 超过部分隐藏或者清除画布(当前清除画布)
        this.succuss = options.succuss;    //擦拭成功后执行方法
        this.startfn = options.startfn; //开始擦拭时调用刮刮乐结果(可以给div换图或者换样式)
        this.isprize = false;    //是否擦拭完毕
    }
    //初始化
    init(){
        this.getsize();
        this.createcanvas();
        this.drawbg();
        this.event();
    }
    //获得容器的宽高(用于设置canvas宽高)
    getsize(){
        this.width = this.obj.offsetwidth;
        this.height = this.obj.offsetheight;
        this.left = this.obj.offsetleft;
        this.top = this.obj.offsettop;
    }
    //创建canvas并设置宽高插入容器中
    createcanvas(){
        let canvas = document.createelement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;
        this.ctx = canvas.getcontext("2d");
        this.obj.append(canvas)
    }//绘制前景图 图片必须预加载
    drawbg(){
        let oimg = new image(),
            that = this;
        oimg.src = that.bgpic;
        oimg.onload=()=>{
            this.touch = true;
            this.ctx.drawimage(oimg,0,0,oimg.width,oimg.height,0,0,this.width,this.height);
            this.ctx.globalcompositeoperation = 'destination-out';    //设置原有内容中与新图形不重叠的部分会被保留
        }
    }
    //添加touch事件
    event(){
        let obj = this.obj,
            that = this;
        obj.addeventlistener("touchstart",event=>{that.touchcanvas(event).bind(this)})
        obj.addeventlistener("touchmove",event=>{that.touchcanvas(event).bind(this)})
        obj.addeventlistener("touchend",event=>{})
    }
    //擦拭canvas
    touchcanvas(event){
        if(!this.touch){
            return false;
        }
        if(!this.isprize){
            this.isprize = true;
            this.startfn();
        }

        var e=window.event||event;
        e.preventdefault();    //禁止ios和安卓默认事件页面下拉动
        this.clearcanvas(e.targettouches[0].pagex-this.left,e.targettouches[0].pagey-this.top);
    }
    //绘制圆形 橡皮擦
    clearcanvas(x,y){
        this.ctx.save();
        this.ctx.beginpath();
        this.ctx.arc(x,y,this.radius,0,2*math.pi);
        this.ctx.fill();
        this.ctx.closepath();
        this.ctx.stroke();
        this.ctx.restore();
        this.compute();
    }
    //计算透明区域
    compute(){
        var pixels = this.ctx.getimagedata(0,0,this.width,this.height).data;
        let transpixels = [];
        for(let i = 0; i < pixels.length; i += 4){
            // 严格上来说,判断像素点是否透明需要判断该像素点的a值是否等于0,
            // 为了提高计算效率,这儿设置当a值小于128,也就是半透明状态时就可以了
            if(pixels[i+3] < 128){
                transpixels.push(pixels[i+3]);
            }
        }
        let area= (transpixels.length / (pixels.length / 4) * 100).tofixed(2);
        if(area>this.area){
            this.touch = false;
            this.ctx.clearrect(0,0,this.width,this.height);
            this.ctx.globalcompositeoperation = 'source-over';
            this.succuss();
        }
    }
    //再来一次(重置)
    reset(){
        this.isprize = false;
        this.drawbg();
    }
}

(第一次写博客,有错请见谅)