css,环形

思路:

1.先利用conic-gradient属性画一个圆,然后再叠加

效果图

javascript 复制代码
<template>
  <div class="ring">
    <div class="content">
      <slot></slot>
    </div>
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs, computed, onMounted } from "vue";
export default defineComponent({
  props: {
    width: {
      type: Number,
      default: 200,
    },
    height: {
      type: Number,
      default: 200,
    },
    color: {
      type: String,
      default: "#fcb844",
    },
    angle: {
      type: Number,
      default: 360,
    },
    total: {
      type: Number,
      default: 360,
    },
    unit: {
      type: String,
      default: "px",
    },
    interval: {
      type: Number,
      default: 20,
    },
    autoPlay: {
      type: Boolean,
      default: true,
    },
  },
  setup(props, { emit }) {
    const datas = reactive({
      timer: null,
      sportAge: 0,
    });
    // 设置渐变
    const bgImage = computed(() => {
      datas.sportAge = props.autoPlay ? datas.sportAge : currentAngle.value;
      return `conic-gradient(${props.color} 0deg, ${props.color} ${datas.sportAge}deg, transparent 0deg)`;
    });
    // 当前度数(deg)
    const currentAngle = computed(() => {
      return ((360 / props.total) * props.angle).toFixed(2);
    });
    // 单位前缀
    const unitSuffix = computed(() => {
      return (data, interval = 0) => {
        return data - interval + props.unit;
      };
    });
    //动画
    const animationPlay = () => {
      datas.timer = setInterval(() => {
        if (currentAngle.value <= datas.sportAge) {
          clearInterval(datas.timer);
          datas.timer = null;
          return;
        }

        datas.sportAge++;
      }, 10);
    };
    onMounted(() => {
      props.autoPlay ? animationPlay() : "";
    });
    return {
      ...toRefs(datas),
      bgImage,
      unitSuffix,
    };
  },
});
</script>
<style lang="less" scoped>
.ring {
  position: relative;
  width: v-bind(unitSuffix(width));
  height: v-bind(unitSuffix(height));
  display: flex;
  align-items: center;
  justify-content: center;
  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: v-bind(unitSuffix(width));
    height: v-bind(unitSuffix(height));
    // background-color: red; /* 对于不支持渐变的浏览器 */
    background-image: v-bind(bgImage);
    border-radius: 50%;
    transform: scale(-1, 1);
  }
  &::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: v-bind(unitSuffix(width, interval));
    height: v-bind(unitSuffix(height, interval));
    border-radius: 50%;
    background-color: #ffffff;
  }
  .content {
    position: absolute;
    z-index: 3;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>
javascript 复制代码
<template>
  <div class="ring_box">
    <div class="inner">
      <ring
        :width="180"
        :height="180"
        :color="innerColor"
        :z-index="2"
        :interval="interval"
      >
      </ring>
      <div class="out">
        <ring :total="3454" :angle="2234" :interval="interval" :z-index="4">
          <ring
            :width="175"
            :height="175"
            :color="innerColor"
            :interval="interval / 2"
            :z-index="4"
          >
            <div>内容</div>
          </ring>
        </ring>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import ring from "./ring.vue";
import { defineComponent, reactive, toRefs } from "vue";
export default defineComponent({
  components: {
    ring,
  },
  setup(props) {
    const datas = reactive({
      width: 180,
      height: 180,
      outColor: "",
      innerColor: "#feedd1",
      interval: 40,
    });
    return {
      ...toRefs(datas),
    };
  },
});
</script>
<style lang="less" scoped>
.ring_box {
  width: 300px;
  height: 300px;
  display: flex;
  align-items: center;
  justify-items: center;
  position: relative;
  .out,
  .inner {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}
</style>
相关推荐
子兮曰5 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋6 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁6 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄7 小时前
JavaScript 隐式全局变量解析
javascript
汉堡大王95278 小时前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大8 小时前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师8 小时前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端