canvas抽奖

2020-01-16  本文已影响0人  小仙有毒_1991
image
要实现的功能

步骤

config → init → loadingImg → drawImg → rotate

1. 配置基本参数
config: {
  num: 6, // 奖品数量
  width: 750,  // canvas宽
  height: 750, // canvas高
  maxw: 140, // 中奖图片的最大宽
  maxh: 100 // 中奖图片的最大高
}
  1. 初始化
//请求服务端获取奖品列表获取奖品数组
 get gitfs = [...] ...
//  获取初始值
this.num = this.gifts.length
this.ctx = this.canvas.getContext('2d')
this.canvas.width = this.config.width
this.canvas.height = this.config.height 
  1. 加载图片
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
    })
  }
  1. 画图
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)
}

  1. 旋转抽奖
//抽奖事件触发
this.pick.addEventListener('click', () => {
     ajax.... // 获取抽奖结果
     this.rotate(deg)      //  转盘转到指定位置 
 })
 // 旋转角度计算
  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)`
  }

通过css加上缓动

transition:all 5s ease-in-out

上一篇 下一篇

猜你喜欢

热点阅读