如何动态监控 Circle 环形进度条的当前进度点 并添加自定义元素跟随

117 阅读2分钟

本期为您详细讲解如何动态监控 Circle 环形进度条的当前进度点 并添加自定义元素跟随,希望能够帮助到您。

温馨提示:本案例 vue2 + vant2 源码实现,您可借鉴修改为 vue3 or React。

注:作者声明坚决不丢份!!!直接马国成C档起步,我上早八!!!

say.jpg

一:C档起步,先看效果

组件基本效果:👇

before.png

修改过后的效果:👇

after.png

二:我上早八(源码)!!!

<template>
  <div class="loadings">
    <!-- van-circle 标签中使用到的参数
      v-model       代表 当前进度
      rate          代表 目标进度
      stroke-width  代表 进度条宽度
      color         代表 进度条颜色,传入对象格式可以定义渐变色 
      layer-color   代表 轨道颜色(后续进度还未加载到的空白轨道颜色)
      注:本案例传入的 color 值为渐变色对象 gradientColor,在 data 中定义。
    -->
    <van-circle
      v-model="schedule"
      :rate="schedule"
      :speed="100"
      :stroke-width="30"
      :color="gradientColor"
      layer-color="#EDF1F4"
      class="custom-circle"
    >
       <!-- 
           van-circle 标签中嵌入 template 模板标签,slot 设置为 default,
           此时 template 标签里的内容为自定义内容。 
       -->
      <template slot="default">
        <!-- 下方为显示百分比的背景图,动态设置 style 值,添加 boxPosition 计算方法,动态计算距离左侧和距离顶部的距离 -->
        <img
          class="percentage-box"
          :style="{ left: boxPosition.left, top: boxPosition.top }"
          :src="require('@/assets/imgs/scan/a.png')"
          alt=""
        />
        <!-- 下方div显示百分比,动态设置 style 值,添加 boxPositionLabel 计算方法,动态计算距离左侧和距离顶部的距离 -->
        <div
          class="percentage-box percentage-box-text"
          :style="{
            left: boxPositionLabel.left,
            top: boxPositionLabel.top,
          }"
        >
          {{ schedule }}%
        </div>
        <!-- 下方为显示dot点的图片位置,动态设置 style 值,添加 boxPositionDot 计算方法,动态计算距离左侧和顶部的距离 -->
        <img
          class="percentage-box percentage-box-dot"
          :style="{
            left: boxPositionDot.left,
            top: boxPositionDot.top,
          }"
          :src="require('@/assets/imgs/scan/dot.png')"
          alt=""
        />
      </template>
    </van-circle>
  </div>
</template>
<script>
export default {
  data() {
    return {
      schedule: 94, // 当前进度值
      gradientColor: { // 给 van-circle 标签设置进度条渐变色
        "0%": "#93CFFF",
        "100%": "#0D8FFE",
      },
    };
  },
  // 这里使用计算属性,根据 schedule 进度值变化而变化。注:计算属性需要有依赖
  computed: {
    // 下方三个方法的 radius 变量以及 return 出去的 left、right 可根据实际使用微调
    // 因为是环形进度条,所以就因该想象到自定义元素是根据一个圆形来做旋转的,跟着进度点走的
    boxPositionLabel() {
      const radius = 49; // 进度条半径
      const angle = (this.schedule / 100) * 360 - 90; // 转换为角度
      const radians = (angle * Math.PI) / 180; // 转换为弧度
      return {
        left: 50 + radius * Math.cos(radians) + "%",
        top: 37 + radius * Math.sin(radians) + "%",
      };
    },
    boxPositionDot() {
      const radius = 49; // 进度条半径
      const angle = (this.schedule / 100) * 360 - 90; // 转换为角度
      const radians = (angle * Math.PI) / 180; // 转换为弧度
      return {
        left: 50.1 + radius * Math.cos(radians) + "%",
        top: 47 + radius * Math.sin(radians) + "%",
      };
    },
    boxPosition() {
      const radius = 49; // 进度条半径
      const angle = (this.schedule / 100) * 360 - 90; // 转换为角度
      const radians = (angle * Math.PI) / 180; // 转换为弧度
      return {
        left: 50 + radius * Math.cos(radians) + "%",
        top: 35 + radius * Math.sin(radians) + "%",
      };
    },
    
    // 方法注释:
  
    // 以 boxPosition 为例,它计算并返回一个对象,该对象包含两个属性:left 和 top。
    // const radius = 49 表示进度条的半径。
    // const angle = (this.schedule / 100) * 360 - 90;
    // 这里,将 this.schedule 转换为 0 到 360 之间的角度(表示一个完整的圆),然后,从这个角度中减去 90 度,为了将进度条的起始点从顶部移动到左侧。
    //(因为 Math.cos(0) 是 1,Math.sin(0) 是 0,所以 (50 + radius, 35) 会是圆的顶部中心)。
    
    // 角度到弧度的转换:
    // const radians = (angle * Math.PI) / 180; 由于 JavaScript 的 Math 函数(如 Math.cos 和 Math.sin)期望输入是弧度而不是角度,所以这里将角度转换为弧度。
    
    // 计算 left 和 top 的值:
    // left: 50 + radius * Math.cos(radians) + "%"; 这里,50 是容器或父元素的中心点的 x 坐标(假设容器是 100% 宽)。然后,根据计算出的弧度,使用 Math.cos 函数来确定在 x 轴上的偏移量。最后,将结果转换为百分比字符串。
    // top: 35 + radius * Math.sin(radians) + "%"; 同样,35 是容器或父元素的中心点的 y 坐标(假设容器的高度是 70% 或其他某个值)。然后,使用 Math.sin 函数来确定在 y 轴上的偏移量。最后,将结果转换为百分比字符串。
    
    // 总结: 基于给定的进度 this.schedule 计算一个点在圆形或弧形进度条上的位置,并返回该点的 CSS 定位属性(left 和 top)。计算考虑了进度条的半径和起始角度(从顶部开始,并向左偏移 90 度)。
  },
};
</script>

看到这里给你点个赞👍,感觉有用的记得点赞收藏加关注,持续更新中...


<style lang="less" scoped>
.loadings {
  width: 100%;
  height: 100%;
  margin-top: 100px;
  .custom-circle {
    position: relative;
    width: 330px;
    height: 330px;
    .schedule {
      width: 36px;
    }
  }
  .custom-circle .van-circle__layer {
    position: absolute;
  }
  .custom-circle .van-circle__layer::after {
    content: "";
    position: absolute;
    width: 10px;
    height: 10px;
    background-color: blue;
    border-radius: 50%;
    transform: translateY(-50%);
  }
}
.percentage-box {
  background: rgba(0, 0, 0, 0);
  width: 60px;
  position: absolute;
  top: 0; /* 根据需要调整 */
  left: 50%; /* 根据需要调整 */
  transform: translateX(-50%);
  border-radius: 5px;
  /* 设置背景图像不重复 */
  background-repeat: no-repeat;
  /* 设置背景图像的位置,这里设置为居中顶部 */
  background-position: center top;
  /* 设置背景图像的大小,这里设置为覆盖整个元素 */
  //   background-size: cover;
  /* (可选)设置背景图像固定,不随页面滚动 */
  background-attachment: fixed;
}
.percentage-box-text {
  position: absolute;
  font-size: 20px;
  color: white;
}
.percentage-box-dot {
  position: absolute;
  width: 24px;
}
</style>

注:版权所有,侵权必究。请尊重原创,未经许可禁止用于商业用途。