采黎创意第1期 | 刮刮乐·好运十倍
刮刮乐大家都玩过吧,采黎也是
深受其害,就是忍不住🤣;特别是好运十倍
这一款,总给人一种中奖机率很大的感觉;今天采黎做了一款线上刮刮乐-好运十倍,供大家娱乐。
前言
定制头像2.0上线后,就想过做一个有关创意的专栏;
我自己也喜欢做一个创意、有趣、奇思妙想的项目;短短挤载程序生涯,总要留下点什么!
专栏
请先允许我介绍下我的专栏------采黎创意
顾名思义,这个专栏就是收录我自己做的创意、有趣、好玩的项目大部分是前端,因为是创意专栏,所以不定时更新,可能2天一个,也可以能半月一个,灵感总是那么转瞬即逝,我想把仅有的、缥缈的灵感保存下来。
为了不断更,我在github 新开了100个创意项目,大家可以star一下,有兴趣的小伙伴可以订阅一下专栏,跟随github。
预览效果
还是老规矩,先上链接~
🚀🚀🚀 刮刮乐-体验地址(主站) 🚀🚀🚀
🚀🚀🚀 刮刮乐-体验地址(github pages) 🚀🚀🚀
🚀🚀🚀 github项目地址(欢迎⭐) 🚀🚀🚀
喜欢话,动动小手点个star⭐哦,谢谢!
项目架构
javascript
html | less | fabricjs | vue // html直接引用
所需素材
思路
- 用html还原一个未被刮奖的刮刮乐卡片,用其生成遮罩图片。
- 再用html做一个被刮开后的卡片。
- 将遮罩图绘制在canvas画布上,用擦除画笔为其实现刮刮乐功能。
开发
逻辑梳理
我梳理了以下几点
1. 初始化中奖数字
javascript
awardNum : this.createRandomNum()
/* 获取60以内的随机数,不足2位补零 */
createRandomNum () {
const randomNum = Math.floor(Math.random() * 59) + 1
return randomNum > 9 ? randomNum : '0' + randomNum
}
2. 初始化刮奖数字
幸运十倍总共有10行, 从下往上从1个刮奖数开始叠加,8、9、10行分别为8个刮奖数字
我们先打乱默认的奖金,然后随机初始化刮奖数字
js
defaultNumList: [[500], [60], [60], [20], [200], ['40万'], [10], [100], [40], [500]],
numList: [],
initNumList () {
this.numList = this.defaultNumList.sort(() => Math.random() - 0.5).map((row, rowIndex) => {
const rowTotal = rowIndex > 6 ? 8 : rowIndex + 1
for (let i = 0;i < rowTotal; i++) {
row.unshift(this.createRandomNum())
}
return row
}).reverse()
},
3. 绘制画布、初始化笔刷
这里为大家介绍一下fabricjs的EraserBrush 擦除笔刷,不过fabricjs并未默认构建它,需要我们在构建项里面添加进来。
将这个勾选上进行打包
js
initMask () {
this.canvas = new fabric.Canvas('mask', { isDrawingMode: true });
/* 设置画笔 */
this.canvas.freeDrawingBrush = new fabric.EraserBrush(this.canvas)
this.canvas.freeDrawingBrush.width = this.defaultSize
/* 绘制遮罩卡片 */
const backgroundImageUrl = './img/mask.png'; // 替换为你的底层图像
fabric.Image.fromURL(backgroundImageUrl, (img) => {
img.set({ selectable: false });
img.scaleToWidth(this.canvas.width, true)
this.canvas.add(img);
this.loading = false
});
}
到这里刮刮乐的基本逻辑就都实现了,下面是页面的实现
页面
实现遮罩图片
先做一个宽高为346 * 450的卡片盒子,里面分别为头部、刮奖区域以及释义区域
html
<div class="card">
<!-- 卡片头部 -->
<div class="card-head">
<img src="./img/ten.png" alt="">
<img src="./img/40.png" alt="">
</div>
<!-- 刮奖区域 -->
<div class="card-main"></div>
<!-- 玩法释义 -->
<div v-if="false" class="card-desc">
任意一个"我的号码"与"中奖号码"相同,即可获得该对应的奖金;
如果刮出号码"10",即可获得该行对应奖金的10倍.
</div>
</div>
为卡片添加背景
less
background: #f4f4f4 url("../img/bg.png") center no-repeat;
刮奖区域
刮奖区域是由二维数组 defaultNumList 遍历出来的,一共有10行,每行的最后一个元素为奖金。
html
<div class="card-main">
<div v-for="(row, rowIndex) in numList" :key="rowIndex" class="card-main-row">
<div v-for="(num, numIndex) in row" :key="numIndex" class="card-main-col">
<template v-if="numIndex === row.length - 1">
<div class="gold">
<span>奖金{{ cnNumList[9 - rowIndex] }}</span>
<img src="./img/gold.png" alt="">
</div>
</template>
<template v-else>
<img class="money" src="./img/money.png" alt="">
</template>
</div>
</div>
</div>
定位元素
html
<!-- 定位元素 -->
<!-- 聚宝盆背景 -->
<img class="card-pot" src="./img/pot.png" alt=""></img>
<!-- 点点星星背景 -->
<img class="card-star" src="./img/star.png" alt=""></img>
<!-- 中奖号码区域 -->
<div class="card-award">
<p>中奖号码</p>
<img src="./img/money.png">
</div>
<!-- 10次机会 -->
<div class="card-ten">
<p>10次</p>
<p>中奖机会</p>
</div>
画布区域
html
<!-- canvas画布 -->
<canvas id="mask" width="346" height="450"></canvas>
css 代码看源码,不复杂。
ok,这样我们就画出了未刮奖的效果,然后利用浏览器截个屏,遮罩图就保存下来了
实现被刮开后的页面
为了刮奖效果逼真一些,大体的布局都不能动,只能相应的替换一些元素。
头部区域
头部区域的图片改为"刮奖结果"文字
html
<!-- 卡片头部 -->
<div class="card-head">
<div class="card-head-result">刮奖结果</div>
</div>
刮奖区域
将钱币图片改为刮奖数字
ini
<div class="num">{{ num }}</div>
将金元宝的文字"奖金一"改为具体的中奖数字
html
<div class="gold">
<span>{{ num }}元</span>
<img src="./img/gold.png" alt="">
</div>
中奖区域
将中奖区域的钱币改为数字
html
<!-- 中奖号码区域 -->
<div class="card-award">
<p>中奖号码</p>
<div>{{ awardNum }}</div>
</div>
隐藏10次中奖区域
html
<!-- 10次机会 -->
<div v-if="false" class="card-ten">
<p>10次</p>
<p>中奖机会</p>
</div>
取消卡片背景及其他
如此,我们便得到了刮奖后的效果
优化
1. 优化刮奖笔刷
一千个读者眼中就会有一千个哈姆雷特,有的人想刮快点,有的人想慢慢来,我就是; 我加入了笔刷调节功能,供大家选择。
html
<input v-model="defaultSize" type="range" min="5" max="40" @change="sizeChange">
笔刷默认12, 最小为5,最大为40
js
defaultSize: 12
sizeChange () {
this.canvas.freeDrawingBrush.width = this.defaultSize
}
2. 优化载入
初始化的时候绘制遮罩需要时间,这会导致有闪烁、奖项暴露的情况,我在这里做了载入动画
html
<!--加载中-->
<div v-if="loading" class="loading">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
<div v-show="!loading" class="card-wrap"></div>
这里的loading效果用的elemnet ui
js
/* 初始化为true */
loading: true
/* 绘制完遮罩图后加载动画结束 */
initMask () {
this.canvas = new fabric.Canvas('mask', { isDrawingMode: true });
/* 绘制遮罩卡片 */
const backgroundImageUrl = './img/mask.png'; // 替换为你的底层图像
fabric.Image.fromURL(backgroundImageUrl, (img) => {
this.loading = false
});
}
开源
100个创意项目于今天正式起航,邀诸位一起及见证。
人力终有穷尽时,有志同道合的小伙伴欢迎滴我,一起共勉!
余音
下一个创意项目还没有头绪,俗话说有一就有二,第一个创意项目已经来了,第二个还会远嘛!
期待下一个小创意吧,再会~