vue 实现刮奖


Vue 实现刮奖功能
刮奖功能通常通过 Canvas 实现,结合触摸或鼠标事件来擦除涂层。以下是实现步骤和代码示例:
基础实现思路
- 使用 Canvas 绘制底层奖品和顶层覆盖层
- 监听触摸/鼠标事件,在移动时清除对应区域的像素
- 计算擦除面积比例判断是否完成刮奖
具体实现代码
<template>
<div class="scratch-container">
<canvas
ref="canvas"
@mousedown="startScratch"
@mousemove="scratching"
@mouseup="endScratch"
@touchstart="startScratch"
@touchmove="scratching"
@touchend="endScratch"
></canvas>
</div>
</template>
<script>
export default {
data() {
return {
isDrawing: false,
ctx: null,
canvas: null
}
},
mounted() {
this.initCanvas()
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvas
this.ctx = this.canvas.getContext('2d')
// 设置canvas尺寸
this.canvas.width = 300
this.canvas.height = 150
// 绘制底层内容
this.drawPrize()
// 绘制覆盖层
this.drawCover()
},
drawPrize() {
this.ctx.fillStyle = '#f5f5f5'
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
this.ctx.font = '20px Arial'
this.ctx.fillStyle = '#333'
this.ctx.fillText('恭喜中奖!', 100, 80)
},
drawCover() {
this.ctx.fillStyle = '#999'
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
this.ctx.globalCompositeOperation = 'destination-out'
},
startScratch(e) {
this.isDrawing = true
this.scratch(e)
},
scratching(e) {
if (!this.isDrawing) return
this.scratch(e)
},
endScratch() {
this.isDrawing = false
this.checkCompletion()
},
scratch(e) {
const rect = this.canvas.getBoundingClientRect()
const x = (e.clientX || e.touches[0].clientX) - rect.left
const y = (e.clientY || e.touches[0].clientY) - rect.top
this.ctx.beginPath()
this.ctx.arc(x, y, 15, 0, Math.PI * 2)
this.ctx.fill()
},
checkCompletion() {
const imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height)
const pixels = imageData.data
let transparentPixels = 0
for (let i = 0; i < pixels.length; i += 4) {
if (pixels[i + 3] === 0) {
transparentPixels++
}
}
const ratio = transparentPixels / (pixels.length / 4)
if (ratio > 0.6) {
this.$emit('completed')
}
}
}
}
</script>
<style>
.scratch-container {
display: inline-block;
position: relative;
}
canvas {
border: 1px solid #ddd;
border-radius: 8px;
touch-action: none;
}
</style>
进阶优化方向
- 性能优化:对于大尺寸canvas,可以采用分块检测擦除比例
- 视觉效果:
- 使用粒子效果增强刮擦感
- 添加刮擦音效
- 响应式设计:
mounted() { window.addEventListener('resize', this.resizeCanvas) this.initCanvas() }, methods: { resizeCanvas() { const container = this.$el.parentElement this.canvas.width = container.clientWidth this.canvas.height = container.clientHeight this.initCanvas() } } - 奖品配置:通过props传入奖品信息,实现动态内容
移动端适配要点
- 必须添加
touch-action: none样式防止页面滚动 - 处理touch事件时需要考虑多点触控情况
- 适当增大擦除半径以提高移动端体验
实现时可根据具体需求调整擦除灵敏度、动画效果等参数。核心原理是通过Canvas的绘图API和事件监听实现交互式擦除效果。






