vue2.x 不封闭圆形进度条设计说明学习

文章参考

  1. [CSS/JS]圆形不封闭进度条实现

设计思想

在这里插入图片描述

代码实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>HTTP Status 404 – Not Found</title>
    <style type="text/css">
    * {
      box-sizing: border-box;
    }
      .box{
        height: 300px;
        margin-top: 20px;
      }
      .circle {
        border-radius: 50%;
        height: 200px;
        width: 200px;
        border: 1px solid #722133;
      }
      .colorful {
        border-top: 1px solid green;
        border-right: 1px solid yellow;
        border-bottom: 1px solid blue;
        border-left: 1px solid red;
      }
      .halfcolorful {
        border-top: 1px solid green;
        border-right: 1px solid green;
        border-bottom: 1px solid red;
        border-left: 1px solid red;
      }
      .halfcolorful-transparent {
        border-top: 1px solid red;
        border-right: 1px solid red;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
      }
      .halfcolorful-transparent-active {
        border-top: 1px solid green;
        border-right: 1px solid green;
        border-bottom: 1px solid transparent;
        border-left: 1px solid transparent;
      }
      .half {
        height: 200px;
        width: 100px;
        overflow: hidden;
      }
      /* 旋转到,纯左边的边线是占用一半 */
      .halfrotate {
        transform: rotate(45deg);
      }

      .circle-container {
        position: relative;
        height: 200px;
        width: 200px;
      }
      .left-circle{
        height: 200px;
        width: 100px;
        position: absolute;
        top: 0;
        left: 0;
      }
      .left-circle .circle{
        position: absolute;
        top: 0;
        left: 0;
      }
      .right-circle{
        height: 200px;
        width: 100px;
        position: absolute;
        top: 0;
        right: 0;
      }
      .right-circle .circle{
        position: absolute;
        top: 0;
        right: 0;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="circle"></div>
    </div>

    <div class="box">
      <div class="circle colorful"></div>
    </div>

    <div class="box">
      <div class="circle halfcolorful"></div>
    </div>

    <div class="box">
      <div class="half">
        <div class="circle halfcolorful"></div>
      </div>
    </div>

    <div class="box">
      <div class="half">
        <div class="circle halfcolorful halfrotate"></div>
      </div>
    </div>
    
    <div class="box">
      <div class="half">
        <div class="circle halfcolorful-transparent"></div>
      </div>
    </div>
    
    
    <div class="box circle-container ">
      <div class="half left-circle">
        <div class="circle halfcolorful halfrotate"></div>
      </div>
      <div class="half right-circle">
        <div class="circle halfcolorful-transparent"></div>
      </div>
    </div>

    <div class="box circle-container ">
      <div class="half left-circle">
        <div class="circle halfcolorful halfrotate"></div>
      </div>
      <div class="half right-circle">
        <!-- 旋转到左右各一半是要旋转 45 度 -->
        <div class="circle halfcolorful-transparent" style="transform: rotate(45deg);"></div>
      </div>
    </div>
<hr/>
<div>假设预留的空缺是30度</div>
<!-- 整体圆旋转15度,左右各占15度 -->
<div class="box circle-container " style="transform: rotate(15deg);">
  <div class="half left-circle">
    <div class="circle halfcolorful halfrotate"></div>
  </div>
  <div class="half right-circle">
    <!-- 右侧实际进度条是 (45 - 30),即15度 -->
    <div class="circle halfcolorful-transparent" style="transform: rotate(15deg);"></div>
  </div>
</div>

<div>进度不到一半的效果</div>
<!-- 整体圆旋转15度,左右各占15度 -->
<div class="box circle-container " style="transform: rotate(15deg);">
  <div class="half left-circle">
    <div class="circle halfcolorful halfrotate"></div>
    <!-- 旋转15度 45+15 -->
    <div class="circle halfcolorful halfrotate" style="transform: rotate(60deg);"></div>
  </div>
  <div class="half right-circle">
    <!-- 右侧实际进度条是 (45 - 30),即15度 -->
    <div class="circle halfcolorful-transparent" style="transform: rotate(15deg);"></div>
  </div>
</div>

<div>圆形恰好一半的效果</div>
<!-- 整体圆旋转15度,左右各占15度 -->
<div class="box circle-container " style="transform: rotate(15deg);">
  <div class="half left-circle">
    <div class="circle halfcolorful halfrotate"></div>
    <!-- 旋转15度 45 + 180 -->
    <div class="circle halfcolorful halfrotate" style="transform: rotate(225deg);"></div>
  </div>
  <div class="half right-circle">
    <!-- 右侧实际进度条是 (45 - 30),即15度 -->
    <div class="circle halfcolorful-transparent" style="transform: rotate(15deg);"></div>
  </div>
</div>

<div>圆形超过一半的效果</div>
<!-- 整体圆旋转15度,左右各占15度 -->
<div class="box circle-container " style="transform: rotate(15deg);">
  <div class="half left-circle">
    <div class="circle halfcolorful halfrotate"></div>
    <!-- 旋转15度 45 + 180 -->
    <div class="circle halfcolorful halfrotate" style="transform: rotate(225deg);"></div>
  </div>
  <div class="half right-circle">
    <!-- 右侧实际进度条是 (45 - 30),即15度 -->
    <div class="circle halfcolorful-transparent" style="transform: rotate(15deg);"></div>
    <!-- 全部进度是 旋转角度 15deg -->
    <!-- <div class="circle halfcolorful-transparent-active" style="transform: rotate(15deg);"></div> -->
    <!-- 全部不选中,旋转角度是 -135deg -->
    <!-- <div class="circle halfcolorful-transparent-active" style="transform: rotate(-135deg);"></div> -->
    <!-- 旋转25度角 即 (-135 + 25) -->
    <div class="circle halfcolorful-transparent-active" style="transform: rotate(-110deg);"></div>
  </div>
</div>

  </body>
</html>

参考别人代码实现

<!DOCTYPE html>
<html>

<head>
  <title>圆形未封闭进度条</title>
</head>

<body>
  <ul>
    <li>画圆通过 border-radius 来控制,即可以控制4条边,分别代表 90 180 270 360 度</li>
    <li>设置一个圆形的一半,overflow 为hidden,通过旋转角度内部圆,可以控制显示的角度</li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
  <div class="container">
    <div class="progress">
      <!-- 右半圆容器,只有半圆 -->
      <div class="wrapper right">
        <!-- 
          全圆大小,一半是选中的颜色,一半是非选中的颜色,半圆是通过两个边框设置而成
          优势:
            一半圆圈是选中的,一半圆是非选中的,画圆非常方便
        -->
        <div class="circle rightcircle-box"></div>
        <div class="circle rightcircle" id="right"></div>
      </div>
      <!-- 左半圆 -->
      <div class="wrapper left">
        <!-- 全圆大小,一半是选中的颜色,一半是非选中的颜色,半圆是通过两个边框设置而成 -->
        <div class="circle leftcircle-box"></div>
        <div class="circle leftcircle" id="left"></div>
      </div>
    </div>
    <div class="input">
      <input type="text" id="num">
      <button id="btn">点击</button>
    </div>
    <p id="score"></p>
  </div>
  
  <script type="text/javascript">
  function circleOfScore(index) {
    var score = index ? index : 0;
    var right = 100 * 180 / 270;
    var left = 100 - right;
    var rightDeg;
    var leftDeg;
    var rightCircle = document.getElementById("right");
    var leftCircle = document.getElementById("left");
    var scorenum = document.getElementById("score");
    scorenum.innerHTML = index;

    if (score <= right) {
      rightDeg = score / right * 180 - 135;
      leftDeg = -135;
    } else if (score < 100) {
      rightDeg = 45;
      leftDeg = (score - right) / 100 * 135 - 135;
    } else {
      rightDeg = 45;
      leftDeg = -75;
    }

    rightCircle.style.transform = 'rotate(' + rightDeg + 'deg)';
    leftCircle.style.transform = 'rotate(' + leftDeg + 'deg)';

  }

  var btn = document.getElementById("btn");
  btn.onclick = function() {
    var num = document.getElementById("num").value;
    circleOfScore(num);
  }
  </script>
  <style type="text/css">
  /* 圆环 */
  .container {
    width: 475px;
    height: 600px;
  }


  .progress {
    position: relative;
    width: 400px;
    height: 400px;
    bottom: -40px;
    top: 206px;
    left: 268px;
    transform: rotate(-120deg);
  }

  .progress .wrapper {
    width: 200px;
    height: 400px;
    position: absolute;
    top: 0;
    overflow: hidden;
  }

  .progress .left {
    left: 0;
  }

  .progress .right {
    right: 0;
  }
  /* 全圆大小 */
  .progress .circle {
    width: 384px;
    height: 384px;
    border: 8px solid transparent;
    border-radius: 50%;
    position: absolute;
    top: 0;
    transform: rotate(-135deg);
  }

  .progress .rightcircle-box {
    border-top: 8px solid #99edd1;
    border-right: 8px solid #99edd1;
    border-bottom: 8px solid transparent;
    border-left: 8px solid transparent;
    right: 0;
    transform: rotate(45deg);
  }

  .progress .leftcircle-box {
    border-bottom: 8px solid #99edd1;
    border-left: 8px solid #99edd1;
    border-top: 8px solid transparent;
    border-right: 8px solid transparent;
    left: 0;
    transform: rotate(-75deg);
  }

  .progress .rightcircle {
    border-top: 8px solid yellow;
    border-right: 8px solid yellow;
    animation: mymove 5s infinite;
    right: 0;
  }

  .progress .leftcircle {
    border-bottom: 8px solid yellow;
    border-left: 8px solid yellow;
    left: 0;
  }

  p {
    position: absolute;
    z-index: 3;
    top: 257px;
    left: 240px;
    width: 475px;
    font-size: 81px;
    text-align: center;
  }

  .input {
    position: absolute;
    top: 560px;
    left: 405px;
  }

  .input input {
    width: 100px;
    height: 60px;
    font-size: 40px;
  }

  .input button {
    height: 50px;
    width: 80px;
  }
  </style>
</body>

</html>

改成Vue的实现

<template>
  <!-- 整体圆旋转15度,左右各占15度 -->
  <div class="circle-progress circle-container" :style="getCompCircleStyle()">
    <div class="circle-progress__half left">
      <div class="subcircle" :style="getLeftSubCircleUnactiveStyle()"></div>
      <!-- 旋转15度 45 + 180 -->
      <div class="subcircle active" :style="getLeftSubCircleActiveStyle(progress)"></div>
    </div>
    <div class="circle-progress__half right">
      <div class="subcircle" :style="getRightSubCircleUnactiveStyle()"></div>
      <!-- 旋转15度 45 + 180 -->
      <div class="subcircle active" :style="getRightSubCircleActiveStyle(progress)"></div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'Hello',
  data () {
    return {
      // 缺少的角度是 90
      reduceDeg: 60,
      // 当前进度是 30%
      progress: 89,
      // 1% 的角度
      onePercentDeg: 0
    }
  },
  methods: {
    // 获取1% 的角度
    getOnePercentDeg: function () {
      this.onePercentDeg = (360 - this.reduceDeg) / 100
      return this.onePercentDeg
    },
    // 获取左边active样式
    getLeftSubCircleActiveStyle: function (percent) {
      // 这个45度是下边框和left边框的角度差决定的
      // 180 表示恰好将下边框和left边框旋转到右侧,恰好被遮住了,就是所谓的进度为0
      let zeroDeg = 45 - 180
      let oneDeg = this.getOnePercentDeg()
      let deg = percent * oneDeg
      if (deg >= 180) {
        deg = 180
      }
      return `transform: rotate(${deg + zeroDeg}deg);`
    },
    // 根据percent 计算出 获取左边unactive样式
    getLeftSubCircleUnactiveStyle: function () {
      // 这个45度是下边框和left边框的角度差决定的
      let halfDeg = 45
      // let deg = halfDeg + 180
      return `transform: rotate(${halfDeg}deg);`
    },
    // 根据角度,计算出右侧选中需要旋转的角度
    getRightSubCircleActiveStyle: function (percent) {
      // 默认右侧0%的旋转角度, 将下边框和Left边框调整到左侧,因此就需要旋转45度
      let defaultDeg = 45
      let oneDeg = this.getOnePercentDeg()
      let deg = percent * oneDeg
      if (deg >= 180) {
        deg = deg - 180
      } else {
        deg = 0
      }
      return `transform: rotate(${deg + defaultDeg}deg);`
    },
    // 计算出100%没有有进度的旋转角度
    getRightSubCircleUnactiveStyle: function () {
      // 1. 将下边框和Left边框调整到左侧,因此就需要旋转45度
      // 2. 然后根据缺省的角度,剩下的半圆部分,就是 0%的进度 
      // 减去总共的度数,然后左右各一半,因此需要加上 reduceDeg/2
      let deg = 45 + 180 - this.reduceDeg
      return `transform: rotate(${deg}deg);`
    },
    // 获取整个组件旋转的角度
    getCompCircleStyle: function () {
      let deg = this.reduceDeg / 2
      return `transform: rotate(${deg}deg);`
    }
  },
  computed: {
    // 顶部容器 style 样式
    topContainerStyle: function () {
      console.log(this.reduceDeg)
      return `transform: rotate(${this.reduceDeg}deg);`
    }
  }
}
</script>
<style lang="scss" scoped>
$squarelength: 200px;
$activeColor: green;
$unactiveColor: red;

.circle-progress {
  position: relative;
  height: $squarelength;
  width: $squarelength;
  .circle {
    border-radius: 50%;
    height: $squarelength;
    width: $squarelength;
    border: 1px solid #722133;
  }
  &__half {
    height: $squarelength;
    width: calc($squarelength / 2);
    overflow: hidden;
    position: absolute;
    top: 0;
    &.left{
      height: 200px;
      width: 100px;
      position: absolute;
      top: 0;
      left: 0;
      .subcircle{
        position: absolute;
        top: 0;
        height: $squarelength;
        width: $squarelength;
        border-top: 1px solid transparent;
        border-right: 1px solid transparent;
        border-bottom: 1px solid $unactiveColor;
        border-left: 1px solid $unactiveColor;
        border-radius: 50%;
        transform: rotate(45deg);
        &.active{
          position: absolute;
          top: 0;
          height: $squarelength;
          width: $squarelength;
          border-top: 1px solid transparent;
          border-right: 1px solid transparent;
          border-bottom: 1px solid $activeColor;
          border-left: 1px solid $activeColor;
          border-radius: 50%;
          transform: rotate(225deg);
        }
      }
    }
    &.right{
      height: 200px;
      width: 100px;
      position: absolute;
      top: 0;
      right: 0;
      .subcircle{
        position: absolute;
        top: 0;
        right: 0;
        height: $squarelength;
        width: $squarelength;
        border-top: 1px solid transparent;
        border-right: 1px solid transparent;
        border-bottom: 1px solid $unactiveColor;
        border-left: 1px solid $unactiveColor;
        border-radius: 50%;
        transform: rotate(135deg);
        &.active{
          position: absolute;
          top: 0;
          height: $squarelength;
          width: $squarelength;
          border-top: 1px solid transparent;
          border-right: 1px solid transparent;
          border-bottom: 1px solid $activeColor;
          border-left: 1px solid $activeColor;
          border-radius: 50%;
          transform: rotate(225deg);
        }
      }
    }
  }
}
</style>

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值