mpvue小程序营销活动——canvas实现刮刮卡

 

一、效果图

二、说明

1.使用mpVue编写小程序刮刮奖,底部的优惠券信息可以随时变化

2.如果有需要刮奖涂层可以是一个图片,也可以是纯色背景,依据coating变量是否为空来控制选项。

3.如果刮奖涂层是一个图片,在绘制的时候需要注意网络图片不能直接绘制,需要缓存到本地(wx.downloadfile),用本地地址进行绘制,wx.download花费时间,会导致优惠券内容先显示出来,然后涂层才覆盖其上,用couponShow变量(boolean)来控制整个内容显隐,只有当wx.download结束后内容才出现。

4.获取canvas的宽高,利用了以下方式:

wx.createSelectorQuery().select('#scratchCanvas').boundingClientRect(function (rect) {
  this.width = parseInt(res.width)//  获取canvas宽度;
  this.height = parseInt(res.height)//  获取canvas高度
})

 

<template>
  <div class="page" v-if="couponShow">
    <!--优惠券信息-->
    <div class="scratch">
      <div class="coupon-inform">
        <div class="inform-left">
          <div><span class="coupon-price">10</span>元</div>
          <div >满100可用</div>
        </div>
        <div class="inform-right">
          <div class="coupon-name">促销券</div>
          <div class="fitProdDis">全场适用</div>
          <div class="use-date">使用期限:2019.3.1-2019.6.30</div>
        </div>
      </div>
    </div>
    <!--涂层-->
    <canvas  canvas-id="luck" id="scratchCanvas" class="scratchCanvas" style="width:350px ; height: 150px;" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"></canvas>
  </div>
</template>

 初始化全局变量有两种方法:

方法一:在data中定义,在onLoad中初始化

方法二: 在constructor方法中初始,简单明了

<script>
  export default {
    data () {
      return {
        width: '',                   // canvas宽度
        height: '',                  // canvas高度
        canvasId: 'luck',            // canvasId
        maskColor: '#c3c',           // 没有刮奖涂层图片时,纯色涂层颜色
        size: 8,                     //
        r: '',                       // 焦点大小
        area: '',                    // 刮掉面积
        scale: 0.7,                  // 刮奖涂层全部消失比例
        totalArea: '',               // 画布总面积
        coating: 'https://misc.aotu.io/pfan123/wx/placeholder.png',    // 刮刮奖涂层
        couponShow:false         // 如果有刮奖涂层图片,downloadFile花费时间导致优惠券内容先展示出来,用变量控制显隐可解决
      }
    },
    async onLoad () {
      // 初始化画布宽高
      wx.createSelectorQuery().select('#scratchCanvas').boundingClientRect(function (rect) {
        this.width = parseInt(res.width)//  获取canvas宽度;
        this.height = parseInt(res.height)//  获取canvas高度
      })
      // 焦点大小半径
      this.r = this.size * 3
      // 焦点面积
      this.area  = this.r * this.r
      // 画布总面积
      this.totalArea = this.width * this.height
      this.init()
    },
    onShow () {

    },
    methods: {
      /**
       * 初始化变量,方法二,
       * 比较简便、简单明了
       * @author xiaoxiaoxian
       * @date 2019/3/4
       * @param page
       * @param opts
       */
      constructor(page,opts){
        opts = opts || {};
        this.page = page;
        this.canvasId = opts.canvasId || 'luck';
        this.width = opts.width || 300;
        this.height = opts.height || 150;
        this.maskColor = opts.maskColor || '#c3c';
        this.size = opts.size || 8;
        this.r = this.size * 3;
        this.area = this.r * this.r;
        this.scale = opts.scale || 0.70;
        this.totalArea = this.width * this.height;
        this.init();
      },
      /**
       * 调用绘制画布函数
       * @author xiaoxiaoxian
       * @date 2019/3/4
       * @param
       * @param
       */
      init(){
        this.show = false;
        this.clearPoints = [];
        this.ctx = wx.createCanvasContext(this.canvasId, this);
        this.drawMask();
        this.bindTouch();
      },
      /**
       * 绘制画布,
       * 如果刮奖涂层图片不为空,绘制图片,为空设置颜色
       * @author xiaoxiaoxian
       * @date 2019/3/4
       */
      drawMask(){
        let that = this
        if (this.coating !== '') {
          wx.downloadFile({
            url: this.coating,
            success: res => {
              this.couponShow = true
              console.log(res.tempFilePath)
              that.ctx.drawImage(res.tempFilePath, 0, 0, that.width, that.height);
              that.ctx.draw();
            }
          })
        } else {
          this.couponShow = true
          that.ctx.setFillStyle(that.maskColor);
          that.ctx.fillRect(0, 0, that.width, that.height);
          that.ctx.draw();
        }
      },
      /**
       * 擦拭
       * @author xiaoxiaoxian
       * @date 2019/3/4
       */
      eraser(e,bool){
        let len = this.clearPoints.length;
        let count = 0
        let x = e.touches[0].x,
            y = e.touches[0].y;
        let x1 = x - this.size;
        let y1 = y - this.size;
        if(bool){
          this.clearPoints.push({
            x1: x1,
            y1: y1,
            x2: x1 + this.r,
            y2: y1 + this.r
          })
        }
        for (let val of this.clearPoints){
          if(val.x1 > x || val.y1 > y || val.x2 < x || val.y2 < y){
            count++;
          }else{
            break;
          }
        }
        if(len === count){
          this.clearPoints.push({
            x1: x1,
            y1: y1,
            x2: x1 + this.r,
            y2: y1 + this.r
          })
        }
        if (this.clearPoints.length && this.r * this.r * this.clearPoints.length > this.scale * this.totalArea){
          this.show = true;
        }
        this.ctx.clearRect(x1, y1, this.r, this.r);
        this.ctx.draw(true);
      },
      /**
       * 触摸函数
       * @author xiaoxiaoxian
       * @date 2019/3/4
       */
      bindTouch(){
        const _this = this;
        _this.onTouchStart = function(e){
          _this.eraser(e,true);
        }
        _this.onTouchMove = function (e) {
          _this.eraser(e);
        }
        _this.onTouchEnd = function (e) {
          if(_this.show){
            _this.ctx.clearRect(0, 0, _this.width, _this.height);
            _this.ctx.draw();
          }
        }
      }
    }
  }
</script>
<style scoped>
  .page{
    width: 100%;
  }
  .scratchCanvas{
    width: 350px;
    height: 150px;
    margin-right: auto;
    margin-left: auto;
  }
  .scratch{
    background-color: #8799a3;
    width: 100%;
    height: 200px;
    padding-top: 20px;
    position: absolute;
  }
  .coupon-inform {
    width: 300px;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    background-image:url("https://graph.baidu.com/resource/102ce5edbe2786e5b581a01551680938.jpg") ;
    background-size: 100%;
  }
  .inform-left {
    font-size: 12px;
    color: #FF2E36;
    text-align: center;
    line-height: 25px;
    width: 30%;
    padding-top:20px;
    font-family: 'HelveticaNeue-Medium';
  }

  .coupon-price {
    font-size: 30px;
    color: #FF2E36;
  }
  .inform-right {
    font-size: 14px;
    color: #000000;
    margin-left:8%;
    width:62%;
    padding-top:10px;
  }
  .use-date {
    font-size: 12px;
    color: #717171;
    line-height: 25px;
  }
  .coupon-name {
    font-weight: 600;
    line-height: 30px;
  }
</style>

参考文章:https://blog.csdn.net/m0_38082783/article/details/79458895

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值