思路=》 用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(); } }View Code
(第一次寫博客,有錯請見諒)