uniapp解决canvas画圆环,层级过高挡住其他元素,解法1(polygon+遮罩)

<template>
  <view class="progress_box" @click="secondDuce()">
    <view id="circleBg" class="circleBg">
      <div class="circleBg-center"></div>
    </view>
    <view id="circle" class="circle" :style="clipPathStyle ? clipPathStyle : ''">
      <div class="circle-center"></div>
    </view>
    <div id="seconds" class="second">{{ seconds }}</div>
  </view>
</template>

<script>
export default {
  props: {
    circlePgParams: {
      type: Object,
      default: function() {
        return {
          progressRate: 0.85,
          radius: 100,
          lineWidth: 12,
          lineCap: 'round',
          startColor: '#38A4F5',
          endColor: '#38A4F5',
          bgColor: '#EBEBEB',
          title: 300,
          subTitle: '副标题',
          fontSize: 28,
          rpx: 1
        }
      }
    }
  },
  data() {
    return {
      circleStyle: 0,
      circleRadius: 0,
      centerPoision: 0,
      clipPathStyle: '',
      seconds: 0
    }
  },
  mounted() {
    this.seconds = (10 * Math.random()).toFixed(2)
    this.step(this.seconds / 10, 100, 'circle')
    // this.init()
  },
  methods: {
  	//点击触发事件
    secondDuce() {
      this.clipPathStyle = ''
      this.seconds = (10 * Math.random()).toFixed(2)
      //画圆环
      this.step(this.seconds / 10, 100, 'circle')
    },
    /**
     * @params percent 圆环百分比
     * @params r 圆环外径,原div宽的三分之一
     * @params domId dom元素类名
     * @params pxiel 单位
     **/
    async step(percent, r, domId, pxiel = 'px') {
      var _this = this
      // 获取元素
      let view = await uni.createSelectorQuery().in(this)
      await view
        .select('#' + domId)
        .boundingClientRect(function(data) {
          // data - 各种参数
          console.log(data)

          _this.circleStyleFunc(data.width, pxiel, 0)
          let initPercent = 0
          var timer = setInterval(() => {
            if (initPercent < percent) {
              initPercent += 0.02
              initPercent = initPercent > 1 ? 1 : initPercent
              if (initPercent > 0) {
                _this.circleStyleFunc(data.width, pxiel, initPercent)
              }
            } else {
              clearInterval(timer)
              timer = null
              initPercent = 0
            }
          }, 20)
        })
        .exec()
    },
    circleStyleFunc(L, pxiel, percent) {
      if (percent <= 0) return
      // 包含圆环的div长度高度为 L
      var r = L
      // 总共7个点
      var p1 = [L / 2, L / 2],
        p2 = p1,
        p3 = p2,
        p4 = p2,
        p5 = p2,
        p6 = p2
      var angle = Math.PI * 2 * percent.toFixed(1)
      percent = percent > 1 ? 1 : percent
      console.log('percent, angle:', percent, angle)
      if (angle <= Math.PI / 2) {
        p1 = [L / 2, L / 2]
        p2 = [L / 2, L]
        p3 = [L / 2 - r * Math.sin(angle), L / 2 + r * Math.cos(angle)]
        p4 = p3
        p5 = p3
        p6 = p3
      } else if (angle >= Math.PI / 2 && angle <= Math.PI) {
        p1 = [L / 2, L / 2]
        p2 = [L / 2, L]
        p3 = [0, L / 2]
        p4 = [L / 2 - r * Math.cos(angle - Math.PI / 2), L / 2 - r * Math.sin(angle - Math.PI / 2)]
        p5 = p4
        p6 = p4
      } else if (angle >= Math.PI && angle <= 1.5 * Math.PI) {
        p1 = [L / 2, L / 2]
        p2 = [L / 2, L]
        p3 = [0, L / 2]
        p4 = [L / 2, 0]
        p5 = [L / 2 + r * Math.sin(angle - Math.PI), L / 2 - r * Math.cos(angle - Math.PI)]
        p6 = p5
      } else if (angle >= 1.5 * Math.PI && angle <= 2 * Math.PI) {
        p1 = [L / 2, L / 2]
        p2 = [L / 2, L]
        p3 = [0, L / 2]
        p4 = [L / 2, 0]
        p5 = [L, L / 2]
        p6 = [L / 2 + r * Math.cos(angle - (Math.PI * 3) / 2), L / 2 + r * Math.sin(angle - (Math.PI * 3) / 2)]
      }

      let pArr = [p1, p2, p3, p4, p5, p6]
      this.clipPathStyle = ''
      for (let i = 0; i < pArr.length; i++) {
        if (pArr[i]) {
          this.clipPathStyle = this.clipPathStyle + pArr[i][0] + pxiel + ' ' + pArr[i][1] + pxiel
          this.clipPathStyle = this.clipPathStyle + ','
        }
      }

      this.clipPathStyle = 'clip-path: polygon(' + this.clipPathStyle.substring(0, this.clipPathStyle.length - 1) + ');'
      console.log('this.clipPathStyle', this.clipPathStyle)
    },
    init() {
      if (this.circlePgParams) {
        this.circleStyle = Math.ceil(
          (this.circlePgParams.lineWidth / this.circlePgParams.rpx +
            this.circlePgParams.radius / this.circlePgParams.rpx) *
            2
        )
        this.circleRadius = Math.floor((this.circlePgParams?.radius / this.circlePgParams.rpx || 100) / 2) - 10
        this.centerPoision = Math.floor(this.circleStyle / this.circlePgParams.rpx / 2)
        this.drawProgressbg()
        this.drawCircleAnimate()
      }
    }
  }
}
</script>

<style>
.progress_box {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.progress_bg {
  position: absolute;
  width: 30vw;
  height: 30vw;
  display: none;
}
.progress_bar {
  width: 30vw;
  height: 30vw;
  display: none;
}
.circleBg {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 300rpx;
  height: 300rpx;
  border-radius: 50%;
  position: absolute;
  transition: clip-path 0.2s;
  //遮罩,要小于圆环的半径,否则会全遮住
  -webkit-mask: radial-gradient(transparent 70rpx, #000 70rpx);
  mask: radial-gradient(transparent 70rpx, #000 70rpx);
  overflow: hidden;
}
.circleBg-center {
  margin: 17%;
  width: 66%;
  height: 66%;
  border-radius: 50%;
  background: #ebebeb;
}
.circle {
  width: 300rpx;
  height: 300rpx;
  border-radius: 50%;
  position: relative;
  transition: clip-path 0.2s;
  -webkit-mask: radial-gradient(transparent 70rpx, #000 70rpx);
  mask: radial-gradient(transparent 70rpx, #000 70rpx);
  overflow: hidden;
}
.circle-center {
  margin: 17%;
  width: 66%;
  height: 66%;
  border-radius: 50%;
  background: #38a4f5;
}

.second {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 200rpx;
  height: 200rpx;
  line-height: 200rpx;
  text-align: center;
  font-size: 20rpx;
  transform: translate(-50%, -50%);
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值