<template>
  <view class="tm-propressRound d-inline-block">
    <view class="tm-propressRound-text" :style="{
				width:size+'px',
				height:size+'px'
			}">
      <slot name="default" :value="value">
        <text :class="[black?'text-white':'']">{{value}}%</text>
      </slot>
    </view>
    <view class="tm-propressRound-rk">
      <!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
      <canvas
        :canvas-id="cid"
        :id="cid"
        :style="{
				width:size+'px',
				height:size+'px'
			}"
        type="2d"
      ></canvas>
      <!-- #endif -->
      <!-- #ifndef MP-WEIXIN || MP-ALIPAY  -->
      <canvas :canvas-id="cid" :id="cid" :style="{
				width:size+'px',
				height:size+'px'
			}"></canvas>
      <!-- #endif -->
    </view>
  </view>
</template>

<script>
/**
 * 环形进度条
 * @property {Number} value = [] 默认0，推荐使用v-model赋值。value.sync等同。
 * @property {Number} size = [] 默认100，圆环大小。
 * @property {Number} line-width = [] 默认6，圆环线条宽。
 * @property {Array} color = [] 默认['#FF9800','#E91E63','#FF5722']，激活颜色
 * @property {String} bgcolor = [] 默认'#efeff1'，背景颜色
 * @property {Boolea} semicircle = [] 默认 false，是否半圆
 * @property {Function} input 变化时的值。
 * @property {Function} change 变化时的值。
 * @example <tm-propressRound v-model="checked"></tm-propressRound>
 */
export default {
  name: 's-progress-round',
  model: {
    prop: 'value',
    event: 'input',
  },
  props: {
    black: {
      type: Boolean,
      default: false,
    },
    size: {
      type: Number,
      default: 100,
    },
    lineWidth: {
      type: Number,
      default: 10,
    },
    value: {
      type: Number,
      default: 0,
    },
    color: {
      type: Array,
      default: () => {
        return ['#597EF7']
      },
    },
    bgcolor: {
      type: String,
      default: '#e7e7ea',
    },
    semicircle: {
      type: Boolean | String,
      default: false,
    },
  },
  data() {
    return {
      ctx: null,
      timid: null,
      jishu: 0,
      cid: 'fdd_psd',
      is2d: false,
    }
  },
  computed: {},
  created() {
    // #ifdef H5 || APP-VUE || APP-PLUS
    this.cid = uni.$s.guid()
    // #endif
    // #ifdef MP-WEIXIN || MP-ALIPAY
    this.is2d = true
    // #endif
  },
  mounted() {
    this.$nextTick(function () {
      this.inits()
    })
  },
  destroyed() {
    clearInterval(this.timid)
  },
  watch: {
    value: function (newval, oldval) {
      if (newval < 0) {
        this.$emit('input', 0)
        this.$emit('update:value', 0)
        this.$emit('change', 0)
        return
      } else if (newval > 100) {
        this.$emit('input', 100)
        this.$emit('update:value', 100)
        this.$emit('change', 100)
        return
      }
      this.$emit('input', newval)
      this.$emit('update:value', newval)
      this.$emit('change', newval)
      let blv = newval - oldval
      if (newval >= 100) {
        blv = 100 - oldval
      }

      if (blv >= 0) {
        this.startHuiZhi(blv, oldval, true)
      } else {
        if (newval <= 0) {
          blv = oldval
        }

        this.startHuiZhi(Math.abs(blv), oldval, false)
      }
    },
  },
  methods: {
    inits() {
      let t = this
      if (this.is2d) {
        const query = wx.createSelectorQuery().in(this)
        query
          .select('#' + this.cid)
          .node((res) => {
            const canvas = res.node
            const ctx = canvas.getContext('2d')
            const dpr = uni.getSystemInfoSync().pixelRatio
            canvas.width = res.node._width * dpr
            canvas.height = res.node._height * dpr
            ctx.scale(dpr, dpr)
            t.ctx = ctx
            t.creatShape()
            this.startHuiZhi(this.value, 0, true)
          })
          .exec()
      } else {
        this.ctx = uni.createCanvasContext(this.cid, this)
        this.creatShape()
        this.startHuiZhi(this.value, 0, true)
      }
    },
    startHuiZhi(val, oldv, type) {
      clearInterval(this.timid)
      let i = 0
      let t = this

      // #ifdef H5
      this.timid = setInterval(() => {
        i += 1
        if (i >= val) {
          clearInterval(t.timid)
          return
        }
        if (type) {
          t.huizhired(oldv + i, type)
        } else {
          t.huizhired(oldv - i, type)
        }
      }, 5)
      // #endif
      // #ifndef H5
      if (type) {
        t.huizhired(val + oldv, type)
      } else {
        t.huizhired(oldv - val, type)
      }
      // #endif
    },
    // 重新绘制。
    creatShape() {
      if (!this.ctx) return
      let ctx = this.ctx
      let x, y, r
      x = y = this.size / 2
      r = (this.size - this.lineWidth * 2) / 2
      if (this.is2d) {
        ctx.beginPath()
        ctx.lineCap = 'round'
        ctx.lineWidth = this.lineWidth - 1
        ctx.strokeStyle = this.bgcolor
        if (this.semicircle) {
          ctx.arc(x, y, r, Math.PI, 0)
        } else {
          ctx.arc(x, y, r, -90, 2 * Math.PI)
        }
        ctx.stroke()
      } else {
        ctx.beginPath()
        ctx.setLineCap('round')
        ctx.setLineWidth(this.lineWidth - 1)
        ctx.setStrokeStyle(this.bgcolor)
        if (this.semicircle) {
          ctx.arc(x, y, r, Math.PI, 0)
        } else {
          ctx.arc(x, y, r, -90, 2 * Math.PI)
        }
        ctx.stroke()
        ctx.draw(true)
      }
    },
    huizhired(end = 0, type) {
      if (!this.ctx) return
      let ctx = this.ctx

      if (end >= 100) end = 100
      if (end <= 0) end = 0
      let bl = end * 3.6

      bl = bl - 90
      let x, y, r
      x = y = this.size / 2
      r = (this.size - this.lineWidth * 2) / 2
      if (this.is2d) {
        ctx.beginPath()
        ctx.lineCap = 'round'
        ctx.lineWidth = type ? this.lineWidth - 1 : this.lineWidth + 1
        ctx.strokeStyle = this.bgcolor
        if (this.semicircle) {
          ctx.arc(x, y, r, Math.PI, 0)
        } else {
          ctx.arc(x, y, r, -90, 2 * Math.PI)
        }
        ctx.stroke()

        ctx.beginPath()
        ctx.lineCap = 'round'
        ctx.lineWidth = this.lineWidth
        var grd = ctx.createLinearGradient(x, 0, 0, 2 * x)
        let colorl = this.color.length

        if (colorl == 1) {
          grd.addColorStop(1, this.color[0])
        } else if (colorl > 1) {
          for (let i = 0; i < colorl; i++) {
            grd.addColorStop(i / (colorl - 1), this.color[i])
          }
        }
        ctx.strokeStyle = grd

        if (this.semicircle) {
          let val = this.value
          val = val <= 0 ? 0 : val
          val = val >= 100 ? 100 : val
          bl = -(Math.PI - (this.value / 100) * Math.PI)
          ctx.arc(x, y, r, Math.PI, bl)
        } else {
          ctx.arc(x, y, r, -90 * (Math.PI / 180), bl * (Math.PI / 180))
        }
        ctx.stroke()
      } else {
        ctx.beginPath()
        ctx.setLineCap('round')
        ctx.setLineWidth(type ? this.lineWidth - 1 : this.lineWidth + 1)
        ctx.setStrokeStyle(this.bgcolor)
        if (this.semicircle) {
          ctx.arc(x, y, r, Math.PI, 0)
        } else {
          ctx.arc(x, y, r, -90, 2 * Math.PI)
        }

        ctx.stroke()
        ctx.draw(true)

        ctx.beginPath()
        ctx.setLineCap('round')
        ctx.setLineWidth(this.lineWidth)
        var grd = ctx.createLinearGradient(x, 0, 0, 2 * x)
        let colorl = this.color.length

        if (colorl == 1) {
          grd.addColorStop(1, this.color[0])
        } else if (colorl > 1) {
          for (let i = 0; i < colorl; i++) {
            grd.addColorStop(i / (colorl - 1), this.color[i])
          }
        }
        ctx.setStrokeStyle(grd)
        if (this.semicircle) {
          let val = this.value
          val = val <= 0 ? Math.PI : val
          val = val >= 100 ? 100 : val
          bl = -(Math.PI - (this.value / 100) * Math.PI)
          bl = Math.abs(bl) >= Math.PI ? Math.PI : bl
          ctx.arc(x, y, r, Math.PI, bl)
        } else {
          ctx.arc(x, y, r, -90 * (Math.PI / 180), bl * (Math.PI / 180))
        }
        ctx.stroke()
        ctx.draw(true)
      }
    },
  },
}
</script>

<style lang="scss" scoped>
.text-black {
  //color: #000;
}
.text-white {
  color: #fff;
}
.tm-propressRound {
  position: relative;
  .tm-propressRound-text {
    position: absolute;

    display: flex;
    justify-content: center;
    align-items: center;
    align-content: center;
  }
}
</style>
