美文网首页
vue+canvas绘转盘抽奖总结

vue+canvas绘转盘抽奖总结

作者: 小蝴蝶_037a | 来源:发表于2021-03-16 12:03 被阅读0次

    实现目标


    image.png

    旁边的不管,是贴图,主要是中心区域:
    1、先用ctx.arc画出扇形并填充颜色
    2、在相应的扇形内填充奖品的图片和文字
    3、 控制转盘能在指定奖品id的时候能旋转到相应的扇形区域

    • 画出扇形
      关键代码
     let canvasW = canvas.width // 画板的高度
     let canvasH = canvas.height // 画板的宽度
     let colors = ['RGBA(255, 243, 211, 1)', 'RGBA(255, 250, 237, 1)']
     //计算每个奖项所占角度数,以弧度计
      let baseAngle = (Math.PI * 2) / this.prizeList.length  // this.prizeList是我的奖品数组
      for (let index = 0; index < this.prizeList.length; index++) {
            ctx.save()
            let angle = index * baseAngle
            ctx.beginPath() //开始绘制
            ctx.arc(
              canvasW * 0.5,
              canvasH * 0.5,
              0,
              angle,
              angle + baseAngle,
              false
            )
    
            // 把开始绘制弧线的位置移到12点钟方向并绘制弧线
            ctx.arc(
              canvasW * 0.5,
              canvasH * 0.5,
              240,
              baseAngle * index - Math.PI / 2 - baseAngle / 2,
              baseAngle * (index + 1) - Math.PI / 2 - baseAngle / 2,
              false
            )
            // ctx.lineTo ( canvasW * 0.5 , canvasW * 0.5 );
            if (index % 2 == 0) {
              ctx.fillStyle = colors[0] //设置每个扇形区域的颜色
            } else {
              ctx.fillStyle = colors[1] //设置每个扇形区域的颜色
            }
            ctx.stroke() //开始链线
            ctx.fill() //填充颜色
            ctx.restore()
          }
    
    • 填充相应文字和图片
          for (let index = 0; index < this.prizeList.length; index++) {
            let angle = index * baseAngle
            let img = new Image()
            img.src = this.prizeList[index].image
            let that = this
            img.onload = function() {
              ctx.save()
              ctx.beginPath()
              //把画布移到中心。240是我的半径
              ctx.translate(240, 240)
              //rotate方法旋转当前的绘图
              ctx.rotate(angle)
              // 填充文字和图片 具体的位置看自己的设计稿
              ctx.fillText(that.prizeList[index].name, 0, -217)
              ctx.fillText(that.prizeList[index].remark, 0, -194)
              ctx.drawImage(img, -50, -180, 100, 100)
              ctx.closePath()
              ctx.restore()
            }
          }
    
    • 控制转盘 见下列全部代码
    <template>
      <div class="turntable-pages">
        <div ref="turntable" class="turntable" :style="rotateRound">
          <!-- <div
            v-for="(item, index) in prizeList"
            :class="'prize prize' + index"
            :key="index"
          >
            <p>{{ item.name }}</p>
            <p>{{ item.value }}花瓣</p>
            <img :src="item.img" alt="" />
          </div> -->
          <canvas id="wheelCanvas" width="480px" height="480px"
            >抱歉!浏览器不支持。</canvas
          >
        </div>
        <img
          src="../images/turntable_pointer@2x.png"
          alt=""
          class="turntable-btn"
          @click="startTurntable"
        />
      </div>
    </template>
    <script>
    export default {
      props: {
        prizeList: {
          type: Array,
          default: () => [],
        },
        winPrize: {
          type: Object,
          default: () => {},
        },
        toRotate: {
          type: Boolean,
          default: false,
        },
      },
      data() {
        return {
          prizeNum: 6, //奖品摆放数量
        }
      },
      filters: {
        // 处理超长名字
        formatName(name, len) {
          return name.length >= len ? name.slice(0, len) + '...' : name
        },
      },
      computed: {
        //控制转盘转到准确位置
        rotateRound() {
          if (this.toRotate) {
            const count = this.prizeList.findIndex(
              item => item.id === this.winPrize.prizeId
            )
            let num = 360 - count * (360 / this.prizeList.length)
            return {
              transform: `rotate(${360 * 3 + num}deg)`,
              transition: 'all 5s',
            }
          } else {
            return {}
          }
        },
      },
      watch: {
        prizeList(val) {
          if (val.length > 0) {
            this.drawing()
          }
        },
      },
      mounted() {
        this.$refs.turntable.addEventListener(
          'webkitTransitionEnd',
          this.init,
          false
        )
        this.drawing()
      },
      methods: {
        //开启转盘
        startTurntable() {
          // 去修改this.toRotate的值为true,并请求后端抽奖的结果
          this.$emit('startTurn')
        },
        //弹出中奖弹框
        init() {
          this.$emit('showPrizePopup')
        },
        // 绘图
        drawing() {
          let canvas = document.getElementById('wheelCanvas')
          let ctx = canvas.getContext('2d')
          let canvasW = canvas.width // 画板的高度
          let canvasH = canvas.height // 画板的宽度
          //计算每个奖项所占角度数,以弧度计
          let baseAngle = (Math.PI * 2) / this.prizeList.length
          ctx.clearRect(0, 0, canvasW, canvasH) //去掉背景默认的黑色
          ctx.strokeStyle = 'RGBA(249, 228, 178, 1)' //设置画图线的颜色
          ctx.font = '22px PingFangSC-Semibold' //设置字号字体
          let colors = ['RGBA(255, 243, 211, 1)', 'RGBA(255, 250, 237, 1)']
          // let colors = ['#fff', '#000']
          for (let index = 0; index < this.prizeList.length; index++) {
            ctx.save()
            let angle = index * baseAngle
            // let angle = 0 * baseAngle
            ctx.beginPath() //开始绘制
            ctx.arc(
              canvasW * 0.5,
              canvasH * 0.5,
              0,
              angle,
              angle + baseAngle,
              false
            )
    
            // 把开始绘制弧线的位置移到12点钟方向并绘制弧线
            ctx.arc(
              canvasW * 0.5,
              canvasH * 0.5,
              240,
              baseAngle * index - Math.PI / 2 - baseAngle / 2,
              baseAngle * (index + 1) - Math.PI / 2 - baseAngle / 2,
              false
            )
            // ctx.lineTo ( canvasW * 0.5 , canvasW * 0.5 );
            if (index % 2 == 0) {
              ctx.fillStyle = colors[0] //设置每个扇形区域的颜色
            } else {
              ctx.fillStyle = colors[1] //设置每个扇形区域的颜色
            }
            ctx.stroke() //开始链线
            ctx.fill() //填充颜色
            ctx.restore()
          }
          ctx.textAlign = 'center'
          ctx.textBaseline = 'middle'
          ctx.fillStyle = 'rgba(255, 67, 93, 1)'
          for (let index = 0; index < this.prizeList.length; index++) {
            let angle = index * baseAngle
            let img = new Image()
            img.src = this.prizeList[index].image
            let that = this
            img.onload = function() {
              ctx.save()
              ctx.beginPath()
              //把画布移到中心
              ctx.translate(240, 240)
              //rotate方法旋转当前的绘图
              ctx.rotate(angle)
              // 填充文字和图片
              ctx.fillText(that.prizeList[index].name, 0, -217)
              ctx.fillText(that.prizeList[index].remark, 0, -194)
              ctx.drawImage(img, -50, -180, 100, 100)
              ctx.closePath()
              ctx.restore()
            }
          }
        },
      },
    }
    </script>
    <style lang="scss" scoped>
    .turntable-pages {
      position: absolute;
      width: 680px;
      height: 680px;
      top: 266px;
      left: 50%;
      transform: translateX(-50%);
      font-family: PingFang SC;
      .turntable-btn {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 121px;
        height: 136px;
      }
      .turntable {
        width: 680px;
        height: 680px;
        position: relative;
        background: url('../images/turntable.png') no-repeat;
        background-size: 100% 100%;
        .prize {
          position: absolute;
          width: 474px;
          height: 474px;
          top: 50%;
          left: 50%;
          border-radius: 50%;
          text-align: center;
          // margin-top: 5px;
          transform: translate(-50%, -50%);
          p {
            text-align: center;
            font-size: 22px;
            font-weight: 600;
            color: #ff435d;
            margin-top: 4px;
            &:first-child {
              margin-top: 10px;
            }
          }
          img {
            width: 96px;
            height: 96px;
          }
        }
        #wheelCanvas {
          position: absolute;
          top: 50.5%;
          left: 50%;
          transform: translate(-50%, -50%);
          width: 474px;
          height: 474px;
          border-radius: 50%;
        }
      }
    }
    </style>
    
    
    

    相关文章

      网友评论

          本文标题:vue+canvas绘转盘抽奖总结

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