svg或css,写loading圆环和百分比
TL;DR
- svg写圆环就是利用
stroke-dasharray
- 纯css写圆环是利用
border-radius rect rotate
- 大约就是这种效果
svg写圆环
css的步骤很多,可以的话优先svg写圆环。
- mdn上svg画circle
- mdn上stroke-dasharray的理解,就是
实线的长度 空白的长度 实线的长度 空白的长度 。。。
- 掘金上stroke-dasharray和stroke-dashoffset属性的解释
<!-- 本地或者线上跑个demo 修改 stroke-dasharray="0 1069"的第一个值就能看到圆环--> <svg width="440" height="440"> <!-- 底部的灰色背景圆环 --> <circle cx="220" cy="220" r="170" stroke-width="50" stroke="#D1D3D7" fill="none"></circle> <!-- 需要显示的圆环 通过修改 stroke-dasharray="0 1069"的0值那块,(角度/360) = 圆弧长度/周长 这里的圆弧长度就是第一个值--> <circle cx="220" cy="220" r="170" stroke-width="50" stroke="#00A5E0" fill="none" transform="matrix(0,-1,1,0,0,440)" stroke-dasharray="0 1069"></circle> <!-- transform="matrix(0,-1,1,0,0,440)"这个是让实线从12点开始 需要研究的话 文章末尾有相关链接 --> </svg>
vue写个动态圆环组件
- 自定义:圆环显示的百分比、外圆环的直径、圆环宽度、颜色、圆环内文字以及文字大小
- 使用方式
<ring rate="0.6" size="60" stroke-width="10" stroke-color="#8C95FF" text="及格" text-size="30"/>
- 组件的具体代码如下
<template> <div class="parent-element-center"> <svg :width="diameterShow" :height="diameterShow" :viewbox="viewbox"> <circle :cx="size" :cy="size" :r="raduisActual" :stroke-width="strokeWidth" stroke="#eee" fill="none"></circle> <circle v-if="rate" :text="text" :cx="size" :cy="size" :r="raduisActual" :stroke-width="strokeWidth" :stroke="strokeColor" fill="none" :transform="transform" :stroke-dasharray="strokeDasharray" stroke-linecap="round"></circle> </svg> <div class="element-center" :style="textStyle">{{ text }}</div> </div> </template> <script> export default { props: { // 圆环外圈的直径 size: { default: 175 }, // 圆环的小宽度 strokeWidth: { default: 5 }, // 圆环的颜色 strokeColor: { default: '#00D476' }, // 圆环显示的百分比 这边是小数 rate: { default: 0.5 }, // 圆环里面的文字 这里的文字如果跟rate息息相关 可以放到computed计算 text: { default: 50 }, // 圆环里面的文字的fontSize大小 textSize: { default: 20 } }, computed: { raduisActual () { return this.size - this.strokeWidth }, diameterShow () { return 2 * this.size }, viewbox () { return `0 0 ${this.diameterShow} ${this.diameterShow}` }, strokeDasharray () { const perimeter = Math.PI * 2 * this.raduisActual const showLength = this.rate * perimeter - 3 return `${showLength} 1000` }, transform () { return `matrix(0,-1,1,0,0,${this.diameterShow})` }, textStyle () { let res = {} res.fontSize = `${this.textSize}px` return res } } } </script> <style scoped> .parent-element-center{ position: relative;display: inline-block; } .element-center { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size:40px; font-weight: bold; } </style>
纯css 写圆环
逻辑有点复杂,所以按步骤拆分了
1. 写个圆。
so easy。设个宽高,设置radius,搞定。
<div class="circle" style="width: 100px;height:100px;border-radius:100px;background-color: skyblue;">
2. 写个圆环。
有点难度。细细一想,加个border, 背景色干掉,yeah~。 这个逻辑得记住,也就是圆变成圆环两步:
- 背景色处理(背景色不设置,或者背景色是白色之类的hack)
- 加个border
<div class="ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid skyblue;">
3.显示半个圆环。
哟,嗯,拿个方块,盖住右边不就行了。这边想再升级下,试试用clip
属性。
<!-- 圆环用到了border,计算一半的时候总是计算border很是憋手,索性加个 box-sizing: border-box; --> <div class="left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid skyblue;position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;"></div> <div class="right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid skyblue;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;"></div> <!-- 当然 如果不想用 box-sizing: border-box; 也可以 代码如下 注意计算的clip--> <div class="left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid skyblue;position:absolute;clip:rect(0 54px 108px 0);"></div>
4.一个圆环,左边和右边不同色
想想就是上面的拼一波呗~
<div style="width: 100px;height:100px;position: relative;"> <div class="left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid blueviolet;position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;"></div> <div class="right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid skyblue;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;"></div> </div>
5.两个圆环交叉
就是两个圆环有重叠的部分,其实就是将圆环旋转下,这里为了后期的铺垫,将左边的旋转,右边的作为底色。为了突出层级关系,用到z-index
。
<div style="width: 100px;height:100px;position: relative;"> <div class="bg-right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 1;"></div> <div class="front-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 2;transform: rotate(60deg);"></div> </div>
6.怎么将左边非重叠的部分隐藏掉,只显示重叠部分
其实就是再拿个半圆放在左边部分,这个半圆的颜色和底色一致,造成假象。 这时候,其实通过控制front-left-half-ring
的rotate能得到小于180度以内的圆弧
<div style="width: 100px;height:100px;position: relative;"> <div class="bg-right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 1;"></div> <div class="front-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 2;transform: rotate(60deg);"></div> <!-- 遮掉左边的非重叠部分 --> <div class="bg-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 3;"></div> </div>
7.显示超过180度的圆环
上面的超过180度就有毛病了,毕竟我们只有半个圆弧。那怎么办呢。继续制造假象! 说起来你可能不想相信,就是再写个右半圆,旋转,原来的保持不动。
<div style="width: 100px;height:100px;position: relative;"> <div class="bg-right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 1;"></div> <div class="front-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 2;transform: rotate(180deg);"></div> <div class="bg-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 3;"></div> <!-- 想要240度圆环的话 这边旋转 240-180=60 --> <div class="right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 4;transform: rotate(60deg);"></div> </div>
上面的颜色仅仅为了理解,为了显示完美,请将rgba(0,200,0,0.7)
的透明度去掉,效果就很完美了。
8.能显示百分比的圆环
其实直接写个标签在里面,然后(旋转的度数/360 = 百分比),以此求出旋转的度数。
<div style="width: 100px;height:100px;position: relative;display: flex;justify-content: center;align-items: center;"> <div class="bg-right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 1;"></div> <!-- 72/360=20% --> <div class="front-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 2;transform: rotate(72deg);"></div> <div class="bg-left-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid #000;position:absolute;clip:rect(0 50px 100px 0);box-sizing: border-box;z-index: 3;"></div> <!-- 想要240度圆环的话 这边旋转 240-180=60 --> <div class="right-half-ring" style="width: 100px;height:100px;border-radius:100px;border:4px solid rgba(0,200,0,0.7);position:absolute;clip:rect(0 100px 100px 50px);box-sizing: border-box;z-index: 4;transform: rotate(60deg);"></div> <span id="progress">20%</span> </div>