首页 前端知识 使用CSS制作动态的环形图/饼图

使用CSS制作动态的环形图/饼图

2024-06-22 01:06:39 前端知识 前端哥 435 74 我要收藏

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

转载请注明出处或者链接地址:https://www.qianduange.cn//article/13246.html
评论
发布的文章

Java操作读取JSON文件

2024-07-21 00:07:04

Vue3.0环境搭建之npm的安装

2024-07-21 00:07:09

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!