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(); } }
(第一次写博客,有错请见谅)
下一篇: 如何超越英伟达?