使用纯 CSS + Animation + conic-gradient 实现一个环形图。
饼图的实现思路和环形图一样,去掉中间的圆形遮盖 after 伪类元素即可。
一、构建基础样式
构建圆形节点和中间的遮盖元素。
<style>
body {
background-color: rgb(130, 226, 255);
}
.circle {
top: 160px;
left: 160px;
width: 300px;
aspect-ratio: 1;
border: 1px solid white;
border-radius: 50%;
position: relative;
&::after {
content: "";
position: absolute;
top: 7px;
left: 7px;
width: 286px;
height: 286px;
border-radius: 50%;
background: rgb(0, 183, 255);
display: block;
box-sizing: border-box;
}
}
</style>
<body>
<div class="circle"></div>
</body>
二、设置环形、饼图
设置锥形渐变,设置三个颜色(transparent,white,transparent),方便后边通过动画动态调整
.circle {
...
background: conic-gradient(transparent 0 0, white 0 90deg, transparent 90deg 360deg);
&::after {
...
}
}
三、添加动画
添加动画前,将 background 重置一下
.circle {
...
background: conic-gradient(transparent 0 0, white 0 0, transparent 0 360deg);
&::after {
...
}
}
然后添加动画
.circle {
...
animation: rotated 10s linear infinite;
&::after {
...
}
}
@keyframes rotated {
0% {
background: conic-gradient(transparent 0 0, white 0 0, transparent 0 360deg);
}
12% {
background: conic-gradient(transparent 0 0, white 0 90deg, transparent 90deg 360deg);
}
25% {
background: conic-gradient(transparent 0 90deg, white 90deg 90deg, transparent 90deg 360deg);
}
37% {
background: conic-gradient(transparent 0 90deg, white 90deg 180deg, transparent 180deg 360deg);
}
50% {
background: conic-gradient(transparent 0 180deg, white 180deg 180deg, transparent 180deg 360deg);
}
62% {
background: conic-gradient(transparent 0 180deg, white 180deg 270deg, transparent 270deg 360deg);
}
75% {
background: conic-gradient(transparent 0 270deg, white 270deg 270deg, transparent 270deg 360deg);
}
87% {
background: conic-gradient(transparent 0 270deg, white 270deg 360deg, transparent 360deg 360deg);
}
100% {
background: conic-gradient(transparent 0 360deg, white 360deg 360deg, transparent 360deg 360deg);
}
}
可以看到,为渐变gradient的元素设置animation、transition是不会有过渡的效果。这是由于gradient属性并不像width这类型的属性一样,无法通过gradient的变化实现过渡效果。
四、解决过渡不生效的问题
使用 @property 自定义属性,在 gradient 各个颜色的起始、结束角度上使用。
重新调整 @keyframes 中变化的属性,不改变 gradient,而是改变我们自定义的 angle 属性。
CSS变量和@property-CSDN博客
<style>
body {
...
}
@property --angle1 {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
@property --angle2 {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
.circle {
...
background: conic-gradient(transparent 0 var(--angle1), white var(--angle1) var(--angle2), transparent var(--angle2) 360deg);
...
&::after {
...
}
}
@keyframes rotated {
0% {
--angle1: 0deg;
--angle2: 0deg;
/* background: conic-gradient(transparent 0 0, white 0 0, transparent 0 360deg); */
}
12% {
--angle1: 0deg;
--angle2: 90deg;
/* background: conic-gradient(transparent 0 0, white 0 90deg, transparent 90deg 360deg); */
}
25% {
--angle1: 90deg;
--angle2: 90deg;
/* background: conic-gradient(transparent 0 90deg, white 90deg 90deg, transparent 90deg 360deg); */
}
37% {
--angle1: 90deg;
--angle2: 180deg;
/* background: conic-gradient(transparent 0 90deg, white 90deg 180deg, transparent 180deg 360deg); */
}
50% {
--angle1: 180deg;
--angle2: 180deg;
/* background: conic-gradient(transparent 0 180deg, white 180deg 180deg, transparent 180deg 360deg); */
}
62% {
--angle1: 180deg;
--angle2: 270deg;
/* background: conic-gradient(transparent 0 180deg, white 180deg 270deg, transparent 270deg 360deg); */
}
75% {
--angle1: 270deg;
--angle2: 270deg;
/* background: conic-gradient(transparent 0 270deg, white 270deg 270deg, transparent 270deg 360deg); */
}
87% {
--angle1: 270deg;
--angle2: 360deg;
/* background: conic-gradient(transparent 0 270deg, white 270deg 360deg, transparent 360deg 360deg); */
}
100% {
--angle1: 360deg;
--angle2: 360deg;
/* background: conic-gradient(transparent 0 360deg, white 360deg 360deg, transparent 360deg 360deg); */
}
}
</style>
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
background-color: rgb(130, 226, 255);
}
@property --angle1 {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@property --angle2 {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.circle {
top: 160px;
left: 160px;
width: 300px;
aspect-ratio: 1;
border-radius: 50%;
position: relative;
background: conic-gradient(transparent 0 var(--angle1), white var(--angle1) var(--angle2), transparent var(--angle2) 360deg);
animation: rotated 10s linear infinite;
&::after {
content: "";
position: absolute;
top: 7px;
left: 7px;
width: 286px;
height: 286px;
border-radius: 50%;
background: rgb(0, 183, 255);
display: block;
box-sizing: border-box;
}
}
@keyframes rotated {
0% {
--angle1: 0deg;
--angle2: 0deg;
/* background: conic-gradient(transparent 0 0, white 0 0, transparent 0 360deg); */
}
12% {
--angle1: 0deg;
--angle2: 90deg;
/* background: conic-gradient(transparent 0 0, white 0 90deg, transparent 90deg 360deg); */
}
25% {
--angle1: 90deg;
--angle2: 90deg;
/* background: conic-gradient(transparent 0 90deg, white 90deg 90deg, transparent 90deg 360deg); */
}
37% {
--angle1: 90deg;
--angle2: 180deg;
/* background: conic-gradient(transparent 0 90deg, white 90deg 180deg, transparent 180deg 360deg); */
}
50% {
--angle1: 180deg;
--angle2: 180deg;
/* background: conic-gradient(transparent 0 180deg, white 180deg 180deg, transparent 180deg 360deg); */
}
62% {
--angle1: 180deg;
--angle2: 270deg;
/* background: conic-gradient(transparent 0 180deg, white 180deg 270deg, transparent 270deg 360deg); */
}
75% {
--angle1: 270deg;
--angle2: 270deg;
/* background: conic-gradient(transparent 0 270deg, white 270deg 270deg, transparent 270deg 360deg); */
}
87% {
--angle1: 270deg;
--angle2: 360deg;
/* background: conic-gradient(transparent 0 270deg, white 270deg 360deg, transparent 360deg 360deg); */
}
100% {
--angle1: 360deg;
--angle2: 360deg;
/* background: conic-gradient(transparent 0 360deg, white 360deg 360deg, transparent 360deg 360deg); */
}
}
</style>
</head>
<body>
<div class="circle"></div>
</body>
</html>
饼图例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
background-color: rgb(130, 226, 255);
}
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.circle {
top: 160px;
left: 160px;
width: 300px;
aspect-ratio: 1;
border: 1px solid white;
border-radius: 50%;
position: relative;
background: conic-gradient(white 0 var(--angle), transparent var(--angle) 360deg);
transition: --angle 0.5s linear;
&:hover {
--angle: 360deg;
}
}
</style>
</head>
<body>
<div class="circle"></div>
</body>
</html>
GIF 略显卡顿🤣🤣