canvas 绘制刮刮卡

2019-04-28 08:21:31来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

思路=》

 用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();
    }
}
View Code

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


原文链接:https://www.cnblogs.com/sublogs/p/10778487.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:[笔记]记录原开发工作在base命名空间下扩展的属性与方法

下一篇:vue slot+传参