当前位置:首页 > VUE

移动端vue实现刮刮卡

2026-01-22 17:48:09VUE

移动端 Vue 实现刮刮卡效果

在移动端实现刮刮卡效果需要结合 Canvas 绘图和触摸事件监听。以下是一个完整的实现方案:

创建 Vue 组件结构

<template>
  <div class="scratch-container">
    <canvas 
      ref="canvas" 
      @touchstart="handleTouchStart" 
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
    ></canvas>
    <div class="prize-content">{{ prizeText }}</div>
  </div>
</template>

初始化 Canvas 和绘图

export default {
  data() {
    return {
      isDrawing: false,
      ctx: null,
      canvas: null,
      prizeText: "恭喜中奖!",
      canvasSize: { width: 300, height: 150 }
    }
  },
  mounted() {
    this.initCanvas();
  },
  methods: {
    initCanvas() {
      this.canvas = this.$refs.canvas;
      this.ctx = this.canvas.getContext('2d');

      this.canvas.width = this.canvasSize.width;
      this.canvas.height = this.canvasSize.height;

      // 绘制覆盖层
      this.ctx.fillStyle = '#999';
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.globalCompositeOperation = 'destination-out';
    }
  }
}

处理触摸事件

methods: {
  handleTouchStart(e) {
    e.preventDefault();
    this.isDrawing = true;
    const pos = this.getTouchPos(e);
    this.ctx.beginPath();
    this.ctx.moveTo(pos.x, pos.y);
  },

  handleTouchMove(e) {
    if (!this.isDrawing) return;
    e.preventDefault();
    const pos = this.getTouchPos(e);
    this.ctx.lineTo(pos.x, pos.y);
    this.ctx.lineWidth = 20;
    this.ctx.lineCap = 'round';
    this.ctx.lineJoin = 'round';
    this.ctx.stroke();
  },

  handleTouchEnd() {
    this.isDrawing = false;
    this.checkScratchCompletion();
  },

  getTouchPos(e) {
    const rect = this.canvas.getBoundingClientRect();
    return {
      x: e.touches[0].clientX - rect.left,
      y: e.touches[0].clientY - rect.top
    };
  }
}

检查刮卡完成度

methods: {
  checkScratchCompletion() {
    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 transparentRatio = transparentPixels / (pixels.length / 4);
    if (transparentRatio > 0.6) {
      this.$emit('completed');
    }
  }
}

添加样式

.scratch-container {
  position: relative;
  width: 300px;
  height: 150px;
  margin: 0 auto;
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  touch-action: none;
}

.prize-content {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff8e1;
  font-size: 18px;
  color: #ff6d00;
}

优化移动端体验

为提升移动端体验,可以添加以下优化:

// 在 mounted 中添加
document.addEventListener('touchmove', this.preventScroll, { passive: false });

// 在 methods 中添加
preventScroll(e) {
  if (this.isDrawing) {
    e.preventDefault();
  }
},

// 在 beforeDestroy 中移除
beforeDestroy() {
  document.removeEventListener('touchmove', this.preventScroll);
}

组件使用示例

<template>
  <div>
    <h3>刮刮卡</h3>
    <scratch-card @completed="handleComplete" />
  </div>
</template>

<script>
import ScratchCard from './ScratchCard.vue';

export default {
  components: { ScratchCard },
  methods: {
    handleComplete() {
      alert('刮卡完成!');
    }
  }
}
</script>

这个实现方案包含了完整的移动端触摸事件处理、Canvas绘图逻辑和刮卡完成度检测,可以直接在Vue项目中使用。

移动端vue实现刮刮卡

标签: 刮刮卡vue
分享给朋友:

相关文章

vue实现自定义登录

vue实现自定义登录

实现自定义登录的基本步骤 在Vue中实现自定义登录功能通常需要结合前端和后端技术。以下是一个基本的实现流程: 创建登录表单组件 使用Vue的单文件组件创建一个登录表单,包含用户名和密码输入框以及提交…

vue实现双折线图

vue实现双折线图

实现双折线图的步骤 安装必要的依赖库(如 ECharts 或 Chart.js),这里以 ECharts 为例: npm install echarts --save 在 Vue 组件中引入 EC…

vue实现选中单元格

vue实现选中单元格

Vue 实现选中单元格的方法 基础实现思路 在 Vue 中实现选中单元格功能,通常可以通过动态绑定 class 或 style 来实现。以下是一个基于表格的简单实现示例: <template…

vue实现密码框的包

vue实现密码框的包

Vue 密码框实现方案 在 Vue 中实现密码框功能,可以通过原生 HTML 结合 Vue 指令或使用第三方组件库完成。以下是几种常见方案: 原生 HTML + Vue 双向绑定 <temp…

vue实现一个标签选择

vue实现一个标签选择

Vue 标签选择组件实现 基础实现 使用 Vue 的 v-for 和 v-model 指令可以快速实现标签选择功能: <template> <div class="tag-s…

vue实现分屏

vue实现分屏

Vue 实现分屏的方法 分屏功能通常用于展示多个独立内容区域,以下是几种常见的实现方式: 使用 CSS Grid 布局 通过 CSS Grid 可以轻松创建分屏布局,在 Vue 组件中直接应用样式…