之前公司項目有一個刮獎小游戲的需求,因此有了本文記錄該“刮刮樂”游戲的實現過程。
話不多說,先上Demo 和 項目源碼 .
2. 實現
我們創建一個 ScrapAward 類,通過傳入 option 和調用其 restart() 方法實現重新開始。
(1)定義 option 參數及 ScrapAward 結構
class ScrapAward { constructor(userOption) { this.option = { canvasId: 'canvas', // canvas的id backgroundImageUrl: '', // 背景圖url width: 320, // canvas寬度 height: 160, // canvas高度 backgroundSize: '100% 100%', coverImage: { // 覆蓋圖層背景圖url url: '', width: 320, height: 160, }, callback: () => {}, // 刮獎完成的回調函數 }; this.ctx = null; this.init(userOption); // 初始化 } // 初始化方法 init(userOption) { } // 重新開始也是一次初始化 restart(userOption) { if (userOption) { this.init(userOption); } else { this.init({}); } }}
(2) init 初始化
首先合并用戶的配置 userOption 和默認 option , 等背景圖片加載完成后調用 fillCanvas()
方法繪制覆蓋層的圖片后設置 canvas 的背景圖。
當上述行為完成后,我們便監聽鼠標或者touch事件。刮獎這一行為其實是canvas對鼠標或者touch的移動路徑進行繪畫,只不過是將繪畫的路徑變成了透明,這種效果我們通過設置 ctx.globalCompositeOperation = 'destination-out';
即可實現。
init(userOption) { // 合并用戶配置 if (Object.assign) { Object.assign(this.option, userOption); } else { extend(this.option, userOption, true); } // 定義一系列變量 let that = this, img = (this.img = new Image()), //背景圖片 imgLoaded = false, //背景圖是否加載完成 canvas = (this.canvas = document.querySelector(`#${this.option.canvasId}`)), hastouch = 'ontouchstart' in window ? true : false, tapstart = hastouch ? 'touchstart' : 'mousedown', tapmove = hastouch ? 'touchmove' : 'mousemove', tapend = hastouch ? 'touchend' : 'mouseup', coverImg = (this.coverImg = new Image()), hasDone = false, // 是否刮獎完畢 coverImgLoad = false; that.mousedown = false; //鼠標的mousedown事件或者touchmove事件是否開啟 // 移除事件監聽,用于重新開始 if (this.canvas) { this.canvas.removeEventListener(tapstart, eventDown); this.canvas.removeEventListener(tapend, eventUp); this.canvas.removeEventListener(tapmove, eventMove); } coverImg.src = this.option.coverImage.url; coverImg.crossOrigin = 'Anonymous'; // 解決一些跨域問題 img.src = this.option.backgroundImageUrl; var w = (img.width = this.option.width), h = (img.height = this.option.height); this.canvasOffsetX = canvas.offsetLeft; this.canvasOffsetY = canvas.offsetTop; canvas.width = w; canvas.height = h; this.ctx = canvas.getContext('2d'); let ctx = this.ctx; this.img.addEventListener('load', backgroundImageLoaded); this.option.coverImage.url && this.coverImg.addEventListener('load', coverImageLoaded); // 背景圖片加載完成后 function backgroundImageLoaded(e) { imgLoaded = true; fillCanvas(); canvas.style.background = 'url(' + img.src + ') no-repeat'; canvas.style.backgroundSize = that.option.backgroundSize || 'contain'; } // 覆 主站蜘蛛池模板: 揭东县| 称多县| 林州市| 汶川县| 河西区| 龙海市| 太康县| 镇沅| 台东市| 报价| 肥东县| 海伦市| 贡觉县| 石楼县| 仪陇县| 天柱县| 平顶山市| 民丰县| 新乡市| 阿鲁科尔沁旗| 东乡| 乌审旗| 雅江县| 桦南县| 茂名市| 疏附县| 保定市| 福鼎市| 铜鼓县| 公安县| 加查县| 油尖旺区| 桦川县| 石泉县| 喜德县| 伊金霍洛旗| 宁化县| 高青县| 和静县| 丰台区| 永新县|