移动端vue实现刮刮卡
实现思路
在移动端Vue中实现刮刮卡效果,核心是利用Canvas绘制蒙层,通过触摸事件擦除蒙层显示底层内容。关键点包括Canvas初始化、触摸事件监听以及擦除算法实现。
基本实现步骤
安装依赖(如需要) 若项目未安装Vue-Touch,可通过npm安装:
npm install vue-touch@next
模板结构
<template>
<div class="scratch-container">
<canvas
ref="canvas"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd">
</canvas>
<div class="prize-content">
<!-- 底层奖品信息 -->
<p>{{ prizeText }}</p>
</div>
</div>
</template>
样式设置
.scratch-container {
position: relative;
width: 300px;
height: 150px;
}
canvas {
position: absolute;
top: 0;
left: 0;
z-index: 2;
background-color: #ccc;
touch-action: none;
}
.prize-content {
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
JavaScript逻辑
export default {
data() {
return {
isDrawing: false,
ctx: null,
prizeText: "一等奖"
}
},
mounted() {
this.initCanvas();
},
methods: {
initCanvas() {
const canvas = this.$refs.canvas;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
this.ctx = canvas.getContext('2d');
this.ctx.fillStyle = '#999';
this.ctx.fillRect(0, 0, canvas.width, canvas.height);
this.ctx.globalCompositeOperation = 'destination-out';
},
handleTouchStart(e) {
this.isDrawing = true;
const touch = e.touches[0];
this.drawCircle(touch.clientX, touch.clientY);
},
handleTouchMove(e) {
if (!this.isDrawing) return;
const touch = e.touches[0];
const rect = this.$refs.canvas.getBoundingClientRect();
const x = touch.clientX - rect.left;
const y = touch.clientY - rect.top;
this.drawCircle(x, y);
},
handleTouchEnd() {
this.isDrawing = false;
this.checkScratchCompletion();
},
drawCircle(x, y) {
this.ctx.beginPath();
this.ctx.arc(x, y, 15, 0, Math.PI * 2);
this.ctx.fill();
},
checkScratchCompletion() {
const imageData = this.ctx.getImageData(
0, 0,
this.$refs.canvas.width,
this.$refs.canvas.height
);
const pixels = imageData.data;
let transparentCount = 0;
for (let i = 0; i < pixels.length; i += 4) {
if (pixels[i+3] === 0) {
transparentCount++;
}
}
const transparency = transparentCount / (pixels.length/4);
if (transparency > 0.7) {
console.log('刮刮卡已完成');
}
}
}
}
优化方案
性能优化 使用requestAnimationFrame优化绘制性能:
handleTouchMove(e) {
if (!this.isDrawing) return;
requestAnimationFrame(() => {
const touch = e.touches[0];
const rect = this.$refs.canvas.getBoundingClientRect();
this.drawCircle(touch.clientX - rect.left, touch.clientY - rect.top);
});
}
适配方案 添加窗口大小变化监听:
mounted() {
this.initCanvas();
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
},
methods: {
handleResize() {
this.initCanvas();
}
}
注意事项
-
移动端需确保添加了viewport meta标签:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> -
对于高清屏设备,需要考虑Canvas的像素比:
initCanvas() { const canvas = this.$refs.canvas; const ratio = window.devicePixelRatio || 1;
canvas.width = canvas.offsetWidth ratio; canvas.height = canvas.offsetHeight ratio;
this.ctx = canvas.getContext('2d'); this.ctx.scale(ratio, ratio); // ...其余初始化代码 }
3. 擦除算法可根据需求调整,如改为矩形擦除:
```javascript
drawRect(x, y) {
this.ctx.fillRect(x-10, y-10, 20, 20);
}






