当前位置:首页 > VUE

移动端vue实现刮刮卡

2026-01-22 17:48:09VUE

移动端vue实现刮刮卡

移动端 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 实现父子组件传值 父组件向子组件传值(props) 父组件通过 v-bind 或简写 : 向子组件传递数据。子组件通过 props 接收数据。 父组件代码: <templat…

vue 实现复选

vue 实现复选

Vue 实现复选功能 在 Vue 中实现复选功能可以通过多种方式完成,以下是常见的几种方法: 使用 v-model 绑定数组 通过 v-model 绑定一个数组,可以自动收集用户选择的复选框值。…

vue实现帖子

vue实现帖子

Vue 实现帖子功能 使用 Vue 实现帖子功能需要结合前端框架和后端数据交互,以下是实现的关键步骤和代码示例。 帖子列表展示 创建帖子列表组件,使用 v-for 渲染帖子数据,通过 axios…

vue评分实现

vue评分实现

Vue 评分组件实现方法 使用第三方库(如 Element UI) 安装 Element UI: npm install element-ui 引入并注册组件: import Vue from…

vue权限实现

vue权限实现

Vue 权限实现方案 基于路由的权限控制 通过路由守卫实现权限验证,在路由配置中添加meta字段标记权限要求。在router.beforeEach中检查用户权限与路由要求的匹配情况。 // rout…

实现简易vue

实现简易vue

实现简易 Vue 的核心思路 Vue 的核心功能包括数据响应式、模板编译和虚拟 DOM。以下是一个简易实现方案,涵盖核心功能模块。 数据响应式系统 通过 Object.definePropert…