vue中用canvas撸一个抽奖

作者: supa同学 | 来源:发表于2018-08-14 11:08 被阅读20次
    GIF.gif
    要实现的功能
    • 分割扇形
    • 图片文字居中
    • 图片最大尺寸限制
    • 动画 缓动

    步骤

    config → init → loadingImg → drawImg → rotate

    1. 配置基本参数
    config: {
      num: 6, // 奖品数量
      width: 750,  // canvas宽
      height: 750, // canvas高
      maxw: 140, // 中奖图片的最大宽
      maxh: 100 // 中奖图片的最大高
    }
    
    2. 初始化
    1. 请求服务端获取奖品列表获取奖品数组
      get gitfs = [...] ...
    
    1. 获取初始值
      this.num = this.gifts.length
      this.ctx = this.canvas.getContext('2d')
      this.canvas.width = this.config.width
      this.canvas.height = this.config.height 
    
    3. 加载图片
    loadingImg () {
       const x = this.config.width / 2
       const y = this.config.height / 2
       const r = this.config.height / 2
    
        if (360 % this.num !== 0) {
          alert('请配置正确奖项数量!')
        }
        Object.keys(this.gifts).forEach(index => {
          let img = new Image()
          img.onload = () => {
          // 开始画图了
          this.drawImg(x, y, r, this.num, this.ctx, index, img)
          }
          img.src = this.gifts[index].image
        })
      }
    
    4. 画图
    drawImg (x, y, r, num, ctx, index, img) {
        ctx.save()
        ctx.beginPath()
        ctx.translate(x, y)
        ctx.moveTo(0, 0)
        // 计算每个扇形旋转的角度
        ctx.rotate(index * (2 * Math.PI - 2 * Math.PI / num))
        // 绘制扇形
        ctx.arc(0, 0, r, 3 * Math.PI / 2 - Math.PI / num, 3 * Math.PI / 2 + Math.PI / num, false)
        // 交叉色渲染
        index % 2 === 0 ? ctx.fillStyle = '#339cf7' : ctx.fillStyle = '#4da9ff'
        ctx.fill()
        // 绘制边框
        ctx.lineWidth = 0.5
        ctx.strokeStyle = '#4da9ff'
        ctx.stroke()
    
        // 绘制奖品图片
        // 目标尺寸
        let _tw = img.width
        let _th = img.height
    
        if (img.width > this.config.maxw || img.height > this.config.maxh) {
          if (img.width / img.height > this.config.maxw / this.config.maxh) {
            // 更宽,按照宽度限定尺寸
            _tw = this.config.maxw
            _th = Math.round(this.config.maxw * (img.height / img.width))
          } else {
            _th = this.config.maxh
            _tw = Math.round(this.config.maxh * (img.width / img.height))
          }
        }
        ctx.drawImage(img, -_tw / 2, -y + 40, _tw, _th)
    
         // 绘制文字
        ctx.fillStyle = '#fff'
        ctx.font = '32px bold'
        ctx.textAlign = 'center'
        ctx.fillText(this.gifts[index].name, 0, -y + 170)
    
        ctx.restore()
        this.css(this.container, 360 / num / 2)
        this.css(this.pick, -360 / num / 2)
    }
    
    5. 旋转抽奖
    1. 抽奖事件触发
    this.pick.addEventListener('click', () => {
         ajax.... // 获取抽奖结果
         this.rotate(deg)      //  转盘转到指定位置 
     })
    
    1. 旋转角度计算
      rotate (deg) {
       // 取个30°以内的随机角度偏转
        this.css(this.canvas, 3600 + deg - 360 / this.num / 2 + Math.floor(Math.random() * 30) * (Math.random() > 0.5 ? 1 : -1))
      },
      css (ele, deg) {
        ele.style.transform = `rotate(${deg}deg)`
        ele.style.webkitTransform = `rotate(${deg}deg)`
      }
    
    1. 通过css加上缓动
      transition:all 5s ease-in-out
    这是正在做的一个项目 抽奖入口在提现成功页面
    qrcode.png

    相关文章

      网友评论

        本文标题:vue中用canvas撸一个抽奖

        本文链接:https://www.haomeiwen.com/subject/ihpmbftx.html