一位作者开源了这个游戏,纯前端实现,原生Canvas
希望大家给他点个star,源码地址:https://github.com/leeseean/sic-bo
这个项目克隆很慢,因为比较大,如果你想知道怎么克隆快,可以看今天公众号第二条推文 《如何把github的clone速度提升到1MB/S》
在我看来,这个作者是有一定技术实力的,对canvas理解和使用,以及浏览器渲染机制,都是比较了解的,还有原生dom操作能力都可以
里面大量使用了canvas的路径绘制、填充,以及requestAnimationFrame
使用原生javascript + html +css
主要绘制是canvas实现
点击想押注的地方
筹码会有一个动画飞向你押注的区域
押注完成后,定时开始摇骰子,开奖
初始调用 init函数,生成canvas画布,挂载onclick事件
init() { let _this = this; _this.loadImage(); _this.scale = screen.width < 1500 ? screen.width / 1920 : 1; let scale = _this.scale; //拿到画布 let canvas_fly = document.getElementById('canvas_fly'); //渲染飞出去的筹码 canvas_fly.width = document.body.clientWidth; canvas_fly.height = 912 * scale || 800; _this.ctxFly = canvas_fly.getContext('2d'); let canvas_stop = document.getElementById('canvas_stop'); //渲染未确认投注放桌面上的筹码 canvas_stop.width = document.body.clientWidth; canvas_stop.height = 912 * scale || 800; _this.ctxStop = canvas_stop.getContext('2d'); let canvas_betted = document.getElementById('canvas_betted'); //渲染确认投注的筹码 canvas_betted.width = document.body.clientWidth; canvas_betted.height = 912 * scale || 800; _this.ctxBetted = canvas_betted.getContext('2d'); //拿到chipsImgObj对象 let img = new Image(); img.onload = function () { _this.chipsImgObj = this; //拿到chipsImgObj对象 } img.src = './images/chips.png'; //确定所用筹码 $('.chips>.chip').off('click').on('click', function (e) { $(this).addClass('on').siblings('.chip').removeClass('on'); _this.priceNum = +$(this).attr('priceNum'); }); $('.chips>.chip10').trigger('click'); //默认筹码10 const pieceIntervalOver = { //连续点击翻倍生不生效的flag 'betFor': false, 'betted': false, 'pieceCount': 0, }; const cancelOk = { ok: false, count: 0, }; //取消完毕,默认false const resetOk = { ok: false, count: 0,// 防止重复点击 } //点击桌面选号 $('[rel="selectCode"]').off('click').on('click', function (e) { if (cancelOk.ok || cancelOk.count === 0) { cancelOk.count = 0; } else { return; //没取消完毕不准过去 } _this.flyState = 'flyTo'; let code = $(this).attr('value'); let method = $(this).attr('method'); let startPos = { x: $(`.chips .chip${_this.priceNum}`).offset().left, y: $(`.chips .chip${_this.priceNum}`).offset().top, }; let endPos = { x: $(this).offset().left + $(this)[0].offsetWidth * scale / 2 - $('.chips>.chip').width() * scale / 2, y: $(this).offset().top + $(this)[0].offsetHeight * scale / 2 - $('.chips>.chip').height() * scale / 2, }; _this.eachBetCount[code] = _this.eachBetCount[code] || 0; _this.eachBetCount[code] += _this.priceNum; _this.betOrderRecords[code] = { //记录order method: method, code: code, price: _this.priceNum, amount: _this.eachBetCount[code], piece: _this.eachBetCount[code], }; let clickedElemOption = { //被点击元素的相关数据 priceNum: _this.priceNum, code: code, position: { x: $(this).offset().left, y: $(this).offset().top, }, width: $(this).outerWidth(), height: $(this).outerHeight(), }; _this.betForRecords.push({ //记录投注 elemOption: copyJSON(clickedElemOption), priceNum: _this.priceNum, startPos, endPos, }); _this.chipFly(_this.ctxFly, _this.ctxStop, _this.chipsImgObj, _this.priceNum, startPos, endPos, clickedElemOption, 10); $('.betMoneyAmount').text(_this.calculateBetMoney()); }); //取消投注 $('.cancelButton').off('click').on('click', function (e) { if (cancelOk.ok || cancelOk.count === 0) { cancelOk.ok = false; } else { return; //没取消完毕不准过去 } if ((pieceIntervalOver.betFor && pieceIntervalOver.betted) || pieceIntervalOver.pieceCount === 0) { } else { return; //上次翻倍全部渲染结束才能进行下一次点击操作,没结束操作无效 } cancelOk.count += 1; pieceIntervalOver.pieceCount = 0; if (_this.betForRecords.length === 0) { return; } _this.flyState = 'flyBack'; //timechunk 分时函数 let i = 0; let interval = setInterval(() => { if (i === _this.betForRecords.length) { cancelOk.ok = true; cancelOk.count = 0; //回到0 _this.betForRecords.length = 0; _this.betOrderRecords = {}; _this.eachBetCount = {}; _this.ctxStop.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight); $('.betMoneyAmount').text(_this.calculateBetMoney()); return clearInterval(interval); } let record = _this.betForRecords[i]; _this.chipFly(_this.ctxFly, _this.ctxStop, _this.chipsImgObj, record.priceNum, record.endPos, record.startPos, record.elemOption, 10); i++; }, 10); }); //重置投注 $('.resetButton').off('click').on('click', function (e) { if (resetOk.ok || resetOk.count === 0) { resetOk.ok = false; } else { return; //没取消完毕不准过去 } if ((pieceIntervalOver.betFor && pieceIntervalOver.betted) || pieceIntervalOver.pieceCount === 0) { } else { return; //上次翻倍全部渲染结束才能进行下一次点击操作,没结束操作无效 } resetOk.count += 1; pieceIntervalOver.pieceCount = 0; if (_this.betForRecords.length === 0 && _this.bettedRecords.length === 0) { return; } _this.flyState = 'flyBack'; //timechunk 分时函数 let i = 0; let interval = setInterval(() => { if (i === _this.betForRecords.length) { _this.betForRecords.length = 0; _this.betOrderRecords = {}; _this.eachBetCount = {}; _this.ctxStop.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight); $('.betMoneyAmount').text(_this.calculateBetMoney()); clearInterval(interval); let j = 0; const _interval = setInterval(() => { if (j === _this.bettedRecords.length) { resetOk.ok = true; resetOk.count = 0; //回到0 _this.bettedRecords.length = 0; _this.ctxBetted.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight); $('.betMoneyAmount').text(_this.calculateBetMoney()); return clearInterval(_interval); } console.log(j) const bettedRecord = _this.bettedRecords[j]; _this.chipFly(_this.ctxFly, _this.ctxBetted, _this.chipsImgObj, bettedRecord.priceNum, bettedRecord.endPos, bettedRecord.startPos, bettedRecord.elemOption, 10); j++; }, 10); return; } const betForRecord = _this.betForRecords[i]; _this.chipFly(_this.ctxFly, _this.ctxStop, _this.chipsImgObj, betForRecord.priceNum, betForRecord.endPos, betForRecord.startPos, betForRecord.elemOption, 10); i++; }, 10); }); //确认投注 $('.betButton').off('click').on('click', function (e) { if (_this.betForRecords.length === 0) { alert('请先下注!'); return; } if (cancelOk.ok || cancelOk.count === 0) { } else { return; //没取消完毕不准过去 } if ((pieceIntervalOver.betFor && pieceIntervalOver.betted) || pieceIntervalOver.pieceCount === 0) { } else { return; //上次翻倍全部渲染结束才能进行下一次点击操作,没结束操作无效 } _this.flyState = 'betted'; _this.bettedRecords = _this.bettedRecords.concat(_this.betForRecords); _this.betForRecords.forEach((record) => { _this.chipFly(_this.ctxFly, _this.ctxBetted, _this.chipsImgObj, record.priceNum, record.endPos, record.endPos, record.elemOption, 30); }); _this.ctxStop.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight); _this.betForRecords.length = 0; _this.betOrderRecords = {}; _this.eachBetCount = {}; }); //翻倍投注 $('.pieceButtoon').off('click').on('click', function (e) { let bettedLen = _this.bettedRecords.length; let betForLen = _this.betForRecords.length; if (bettedLen === 0 && betForLen === 0) { return; } if (cancelOk.ok || cancelOk.count === 0) { } else { return; //没取消完毕不准过去 } if ((pieceIntervalOver.betFor && pieceIntervalOver.betted) || pieceIntervalOver.pieceCount === 0) { pieceIntervalOver.betFor = false; pieceIntervalOver.betted = false; pieceIntervalOver.pieceCount += 1; } else { return; //上次翻倍全部渲染结束才能进行下一次点击操作,没结束操作无效 } //timechunk分时函数,防止短时间多次触发卡死浏览器 let i = 0; let interval_bet = setInterval(() => { if (i === bettedLen) { pieceIntervalOver.betted = true; return clearInterval(interval_bet); } let code = _this.bettedRecords[i]['elemOption']['code']; _this.priceNum = _this.bettedRecords[i]['priceNum']; $(`[rel="selectCode"][value="${code}"]`).trigger('click'); //自动桌面选号点击 i++; }, 10); let j = 0; let interval_betted = setInterval(() => { if (j === betForLen) { pieceIntervalOver.betFor = true; return clearInterval(interval_betted); } let code = _this.betForRecords[j]['elemOption']['code']; _this.priceNum = _this.betForRecords[j]['priceNum']; $(`[rel="selectCode"][value="${code}"]`).trigger('click'); //自动桌面选号点击 j++; }, 10); }); },init函数初始化中将canvas画笔挂载到this中
_this.ctxStop = canvas_stop.getContext('2d'); _this.ctxBetted = canvas_betted.getContext('2d'); ...确认投注后,清空未确认投注放桌面上的筹码画布
$('.betButton').off('click').on('click'、、、 _this.ctxStop.clearRect(0, 0, document.body.clientWidth, document.body.clientHeight);如果没有下注,就提示:
if (_this.betForRecords.length === 0) { alert('请先下注!'); return; }记得给作者点个star哦,这是一个入门canvas的一个很好的开源项目,点击左下角的阅读原文就可以进入到源码地址啦:https://github.com/leeseean/sic-bo
如果深入点的话,可以再学习一下canvas的像素控制,或者pixijs的使用
在线体验这个游戏的地址是:
https://leeseean.github.io/sic-bo/我是Peter,架构设计过20万人端到端加密超级群功能的桌面IM软件,我的微信:CALASFxiaotan
另外欢迎收藏我的资料网站:前端生活社区:https://qianduan.life,感觉对你有帮助,可以右下角点个在看,关注一波公众号:[前端巅峰]