vue 刮刮乐功能实现
<template> <!--游玩区域--> <div class="panel"> <canvas id="canvas" @touchstart.prevent="touchStart($event)" @touchmove.prevent="eventMove($event)" :style='{"background-image":"url("+backgroundImage+")"}' width="550" height="380"></canvas> <div id="canvasMask" v-if="start"> <div class="start" @touchstart="StartTouch()"> <div class="startContain"> <span>刮开试试手气</span> <span >开始刮开</span> </div> <img src="../assets/scratch/u611.png" alt=""> </div> </div> <div class="reStart" v-if="restart"> <span @touchstart="ContinueScratch()">继续刮奖</span> </div> </div> </template> <script> let canvas; let ctx; export default { // inject:["reload"], data(){ return{ start:true, restart:false, clientWidth:null, canvasWidth:null, canvasHeight:null, backgroundImage: require('../assets/scratch/prize2.png'), num:2 } }, mounted(){ this.initCanvas() }, methods:{ initCanvas() { console.log("初始化canvas") canvas = document.getElementById('canvas'); ctx = canvas.getContext('2d'); this.clientWidth = document.documentElement.clientWidth, this.canvasWidth = Math.floor(this.clientWidth * 550 / 750),//canvas宽 = 屏幕宽 * 设计稿里canvas宽 / 750 this.canvasHeight = Math.floor(this.clientWidth * 380 / 750),//canvas高 = 屏幕宽 * 设计稿里canvas高 / 750 canvas.style.width=this.canvasWidth+'px'; canvas.style.height=this.canvasHeight+'px'; console.log(canvas.style.backgroundImage); this.drawPic() }, drawPic() { ctx.beginPath(); ctx.fillStyle = '#999';//刮刮乐图层的填充色 ctx.lineCap = "round";//绘制的线结束时为圆形 ctx.lineJoin = "round";//当两条线交汇时创建圆形边角 ctx.lineWidth = 30;//单次刮开面积 ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); ctx.save();//保存画布上面的状态 ctx.closePath(); // ctx.clip(); ctx.globalCompositeOperation = 'destination-out';//新图像和原图像重合部分变透明 //下面代码是为了修复部分手机浏览器不支持destination-out canvas.style.display="inherit"; }, touchStart(e){ e = e || window.event; if (typeof e.touches !== 'undefined') { e = e.touches[0];//获取触点 } var x = e.pageX-e.target.offsetLeft, y = e.pageY-e.target.offsetTop; ctx.moveTo(x, y); //touchmove事件 this.eventMove(e); }, eventMove(e){ e = e || window.event; if (typeof e.touches !== 'undefined') { e = e.touches[0]; } var x = e.pageX-e.target.offsetLeft, y = e.pageY-e.target.offsetTop; ctx.lineTo(x, y); ctx.stroke(); this.clear(); }, clear() { let data = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight).data,//得到canvas的全部数据 half = 0; //length = canvasWidth * canvasHeight * 4,一个像素块是一个对象rgba四个值,a范围为0~255 for (var i = 3, length = data.length; i < length; i += 4) {//因为有rgba四个值,下标0开始,所以初始i=3 data[i] === 0 && half++;//存在imageData对象时half加1 PS:该像素区域透明即为不存在该对象 } //当刮开的区域大于等于30%时,则可以开始处理结果 if (half >= this.canvasWidth * this.canvasHeight * 0.3) { // alert(111) ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);//清空画布 this.restart=true; } }, StartTouch(){ this.start=false; }, ContinueScratch(){ this.num--; if(this.num<=0){ this.num=0; console.log(this.num) alert("没有剩余刮奖次数") }else{ this.start=true; this.restart=false; ctx.restore();//恢复上面保存的画布内容 this.initCanvas(); } } } } </script> <style scoped> .panel{ } .panel{ } .panel #canvas{ position: absolute; top: 5.5rem; left: 1rem; border-radius: 10%; /* background: url('../assets/scratch/prize2.png'); */ background-size:100% 100%; } .panel #canvasMask{ position: absolute; top: 5.3rem; left: 1rem; width: 6rem; height: 4rem; overflow: hidden; } .panel #canvasMask .start{ width: 6rem; height: 4rem; display: flex; /* background-color: sandybrown; */ padding-left: 1.2rem; padding-top: 0.6rem; } .panel #canvasMask .start img{ display: inline-block; width: 2rem; height: 2rem; } .panel #canvasMask .start .startContain{ padding-top: 0.8rem; } .panel #canvasMask .start .startContain span{ display: block; font-size: 0.3rem; text-align: center; } .panel #canvasMask .start .startContain span:last-child{ margin-top: 0.2rem; font-weight: bold; } .panel .reStart{ position: absolute; top: 8.4rem; left: 2.8rem; color: red; border: 0.01rem solid; border-radius: 0.1rem; padding: 0 0.1rem; } .panel .reStart span{ font-size: 0.4rem; } </style>
徐增友