08_微信小程序之大转盘svg实现

08_微信小程序之大转盘svg实现

一.关于微信小程序对svg的支持

这里先准备一个静态的svg文件做测试


<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g transform="rotate(-67.5,160,160)"><path fill="rgb(215,215,215)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(-22.5,160,160)"><path fill="rgb(254,244,61)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(22.5,160,160)"><path fill="rgb(239,119,131)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(67.5,160,160)"><path fill="rgb(215,215,215)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(112.5,160,160)"><path fill="rgb(254,244,61)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(157.5,160,160)"><path fill="rgb(239,119,131)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(202.5,160,160)"><path fill="rgb(215,215,215)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
  <g transform="rotate(247.5,160,160)"><path fill="rgb(254,244,61)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>g>
svg>

那么接下来我们用image标签来显示下服务器端的一个svg,这里我把上述的svg放到了ftp上


<view class="container">
  <image style="width:600rpx; height: 600rpx;" src="{{ftp_director}}/secs.svg">image>
view>

08_微信小程序之大转盘svg实现_第1张图片

可以看到,微信小程序的image标签是能够正常显示svg类型的网络图片的

接下来,我们把svg文件放到小程序静态资源下,再用image加载看下


<view class="container">
  <image style="width:600rpx; height: 600rpx;" src="../../components/turnable-svg/images/secs.svg">image>
view>

08_微信小程序之大转盘svg实现_第2张图片

可以看到,同样也是能够正常显示的

那么问题来了,实现大转盘功能需要我们根据奖品数量去动态生成扇形数量,组成圆盘,通过上述两种办法明显达不到我们要的效果,那么应该怎么办呢?那么我们可不可以将svg的内容直接设置在image标签上类似base64的方式显示出图片呢,答案当然是可以,那么我们继续,接下来才是重点哦



  

//index.js
//获取应用实例
const app = getApp()

Page({
  data: {
    svgRawStr: '',
    svg: ""
  },
  onLoad: function() {
    var svgRawStr = this.data.svgRawStr
    var svg = "data:image/svg+xml," + svgRawStr
    this.setData({
      svg: svg
    })
  }
})

08_微信小程序之大转盘svg实现_第3张图片

可以看到,同样也是支持的,微信小程序的image标签还是挺强大的

既然我们可以将svg的内容作为一个字符串正常显示在image标签上,而这个字符串我们是可以通过设置的奖品去动态生成的,从而达到我们想要的效果,通过奖品动态生成圆盘

好了,既然有了思路,那我们就基于svg来一步一步实现大转盘的自定义组件

二.界面布局


<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
  <image class="outer" src="./images/outer.png">image>
  <view class="secs">view>
  <image class="start" src="./images/start.png">image>
view>
/* components/turnable-svg/index.wxss */
.turntable {
  position: relative;
  margin-left: 50%;
  transform: translateX(-50%);
}

.outer {
  width: 100%;
  height: 100%;
}

.secs {
  position: absolute;
  left: 40rpx;
  top: 40rpx;
  width: calc(100% - 80rpx);
  height: calc(100% - 80rpx);
}

.start {
  position: absolute;
  width: 112rpx;
  height: 124rpx;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
  z-index: 99;
}
// components/turnable-svg/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    size: {
      type: Number,
      value: 600,
      observer: function(newVal, oldVal) {
        this.setData({
          size: newVal
        })
      }
    },
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

08_微信小程序之大转盘svg实现_第4张图片

三.根据奖品个数绘制扇形组成圆盘

svg绘制规则

<path fill="rgb(215,215,215)" d=" M160, 160 L273.1370849898476, 46.86291501015236 A160, 160 0 0, 1 320, 159.99999999999997 z">path>

确定第一个扇形(与圆右端点重和的扇形),假设扇形半径为r,圆形坐标为c(x, y),夹角为alpha,其中一个端点为(2r,r),则另一个端点坐标为

(cx + r*cos(alpha), cy - r*sin(alpha))


<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
  <image class="outer" src="./images/outer.png">image>
  <view class="secs" style="background-size: cover; background-image: url('{{svg}}')">view>
  <image class="start" src="./images/start.png">image>
view>
// components/turnable-svg/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    size: {
      type: Number,
      value: 600,
      observer: function(newVal, oldVal) {
        this.setData({
          size: newVal
        })
      }
    },
    prizeList: {
      type: Array,
      value: [],
      observer: function(newVal, oldVal) {
        this.setData({
          prizeList: newVal
        })
        this.initTurntable()
      }
    }
  },

  lifetimes: {
    ready: function() {
      this.initTurntable()
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    
  },

  /**
   * 组件的方法列表
   */
  methods: {
    initTurntable: function() {
      var that = this
      const query = that.createSelectorQuery()
      query.select('.secs')
        .fields({ node: true, size: true })
        .exec((res) => {

          var size = res[0].width
          //圆心坐标
          var centerX = res[0].width/2
          var centerY = res[0].height/2

          that.setData({
            centerX: centerX,
            centerY: centerY
          })

          //半径
          var radius = size/2

          //奖品数量
          var num = that.data.prizeList.length

          // 扇形旋转转角度
          var rotateDeg = 360 / num / 2 - 90

          var colors = ['#D7D7D7', '#FEF43E', '#EF7683']
          //参数d
          var mx = centerX
          var my = centerY
          var lx = size
          var ly = centerY
          var ax = centerX
          var ay = centerY
          var deg = 0
          var flag1 = 0
          var flag2 = 1
          var dx = centerX + radius * Math.cos((360 / num)  * (Math.PI / 180))
          var dy = centerY - radius * Math.sin((360 / num)  * (Math.PI / 180))

          var svgRawStr = `${size}" height="${size}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`
          //绘制扇形
          for(var i = 0; i < num; i++) {
            var k = i%3
            var rotate = 360 / num * i + rotateDeg
            var sec = `${rotate},${centerX},${centerY})">${colors[k]}" d="M${mx}, ${my} L${lx}, ${ly} A${ax}, ${ay} 0 0, 0 ${dx}, ${dy} z">`
            svgRawStr += sec
          }
          svgRawStr += ""
          var svg = "data:image/svg+xml," + encodeURIComponent(svgRawStr)
          that.setData({
            svg: svg
          })
        })
    }
  }
})

08_微信小程序之大转盘svg实现_第5张图片

三.关于转盘转动以及奖品摆放可参考 微信小程序之大转盘自定义组件编写 时候不早了,洗洗睡了,不然明天上班要迟到了

你可能感兴趣的:(微信小程序,小程序,移动开发,大转盘)