效果
思路
- 使用 canvas 绘制刮奖灰色遮罩部分
- 监听 touchstart、touchmove 和 touchend 事件
- 在事件中处理擦除效果
rem 环境
本文的 rem 布局基础为:基于宽度为 750px 的设计图,1rem = 100px
编码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"
/>
<title>Document</title>
<script>
// rem适配,基于宽度为 750px 的设计图,1rem = 100px
;(function (doc, win) {
const docEl = doc.documentElement
const isIOS = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
let dpr
dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1
dpr = window.top === window.self ? dpr : 1 // 被iframe引用时,禁止缩放
dpr = 1
const scale = 1 / dpr
const resizeEvt =
'orientationchange' in window ? 'orientationchange' : 'resize'
docEl.dataset.dpr = dpr
const metaEl = doc.createElement('meta')
metaEl.name = 'viewport'
metaEl.content =
'initial-scale=' +
scale +
',maximum-scale=' +
scale +
', minimum-scale=' +
scale
docEl.firstElementChild.appendChild(metaEl)
const recalc = function () {
let width = docEl.clientWidth
if (width / dpr > 750) {
width = 750 * dpr
}
docEl.style.fontSize = 100 * (width / 750) + 'px'
}
recalc()
if (!doc.addEventListener) return
win.addEventListener(resizeEvt, recalc, false)
})(document, window)
</script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
html {
font-size: 14px;
}
.prize_wrapper {
width: 5rem;
height: 2rem;
position: relative;
margin: 1rem auto 0;
}
.prize_wrapper .prize {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
line-height: 2rem;
font-size: 0.5rem;
}
.prize_wrapper .prize_mask {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="prize_wrapper">
<div class="prize"></div>
<canvas class="prize_mask"></canvas>
</div>
</body>
<script type="text/javascript">
// 获取DOM对象
let prizeWrapper = document.querySelector('.prize_wrapper')
let prize = document.querySelector('.prize_wrapper .prize')
prize.innerText = '一等奖'
let prizeMask = document.querySelector('.prize_wrapper .prize_mask')
// 获取根元素的font-size
let rootFontSize = +window
.getComputedStyle(document.querySelector('html'))
.fontSize.replace(/px/, '')
let canvasWidth = rootFontSize * 5 // 设置宽度为5rem
let canvasHeight = rootFontSize * 2 // 设置高度为2rem
let ctx // context 对象
// canvas 初始化
function init() {
prizeMask.setAttribute('width', canvasWidth + 'px')
prizeMask.setAttribute('height', canvasHeight + 'px')
ctx = prizeMask.getContext('2d')
ctx.globalAlpha = 1
ctx.fillStyle = '#ccc'
ctx.fillRect(0, 0, canvasWidth, canvasHeight)
ctx.fillStyle = '#000'
ctx.font = '20px 微软雅黑'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText('刮刮奖', canvasWidth / 2, canvasHeight / 2)
}
init()
// 坐标信息
let mX, mY
let flag = false
prizeMask.ontouchstart = function (e) {
flag = true
document.querySelector('html').style.overflow = 'hidden'
// 如果想要点击之后就开始进行擦除,下方解注释即可
// mX = e.touches[0].pageX - prizeWrapper.offsetLeft // 使用pageX可解决有滚动条时位置错位的问题
// mY = e.touches[0].pageY - prizeWrapper.offsetTop
// drawArc(mX, mY)
}
document.body.ontouchmove = function (e) {
if (flag == true) {
mX = e.touches[0].pageX - prizeWrapper.offsetLeft // 使用pageX可解决有滚动条时位置错位的问题
mY = e.touches[0].pageY - prizeWrapper.offsetTop
drawArc(mX, mY)
}
}
document.body.ontouchend = function () {
flag = false
document.querySelector('html').style.overflow = 'auto'
sayPrize()
}
// 擦除函数
function drawArc(x, y) {
ctx.globalCompositeOperation = 'destination-out' //相交部分不显示
ctx.beginPath()
ctx.fillStyle = 'white'
ctx.moveTo(x, y)
ctx.arc(x, y, 10, 0, 2 * Math.PI)
ctx.fill()
}
// 显示获奖信息
function sayPrize() {
let myImg = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
let num = 0
let max = myImg.data.length / 4
for (let i = 0; i < myImg.data.length; i += 4) {
if (myImg.data[i + 3] <= 200) {
num++
}
}
if (num >= max * 0.2) {
console.log('恭喜您,获得:' + prize.innerText)
// 获奖后重置一下
init()
}
}
</script>
</html>