使用纯 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 略显卡顿🤣🤣