简单的5个<>标签快速实现 漂亮的圆形图(饼图)

371 阅读1分钟

5个<>标签快速实现 漂亮的圆形图(饼图)

最终实现的效果

2022-02-09-14-15-16.png

使用SVG能够很快的实现我们的场景

1. 通过SVG画一个圆形

定义svg文档的高宽 创建一个圆形 半径是100,圆点的定位在中心位,轮廓的宽度10px 颜色红色,填充蓝色

  • r 圆的半径
  • cx 圆点的x坐标
  • cy 圆点的y坐标
  • stroke-width 轮廓的宽度
  • stroke 轮廓的颜色
  • fill 填充颜色
<svg width="210px" height="210px">
  <circle r="100" cx="105" cy="105" stroke-width="10" stroke="red" fill="blue">
  </circle>
</svg>

呈现的效果:

2022-02-09-10-20-40.png

2. 让它漂漂亮亮的

轮廓的颜色定义渐变色,我这里设置 渐变位置 从左上角 往 右下角 渐变 颜色从40%开始 到90%的时候结束

<svg width="230px" height="230px">
    <defs>
      <linearGradient x1="40%" y1="15%" x2="90%" y2="80%" id="linearGradient">
        <stop offset="40%" stop-color='#29CABB' />
        <stop offset="90%" stop-color='#EBD178' />
      </linearGradient>
    </defs>
    <circle r="110" cx="115" cy="115" stroke-width="10" fill="transparent" stroke="#23aaff33" />
    <circle r="100" cx="115" cy="115" stroke-width="12" fill="transparent" stroke="url(#linearGradient)" />
    <text fill="#ffffff" font-size="35" font-family="Verdana" x="58" y="100">
      93.8%</text>
    <text fill="#ffffff" font-size="32" font-family="Verdana" x="65" y="150">
        留存率</text>
  </svg>

添加多了一个圆作为底色 衬托主圆的层次感

<linearGradient> 标签必须在<defs>标签内

fill 填充颜色默认黑色,不需要填充颜色? 只能设置成透明

呈现效果

2022-02-09-11-31-36.png

3. 让它跟数据联动起来

现在只成了一个躯壳 我们要丰富下灵魂 让它动起来

这里可以巧妙的利用 stroke-dasharray 来把轮廓改成虚线

假设把虚线长度设置成23 我们看看效果

<svg width="230px" height="230px">
  .....
    <circle r="100" cx="115" cy="115" stroke-width="12" stroke-dasharray="23" fill="transparent" stroke="url(#linearGradient)" />
  .....

2022-02-09-13-54-45.png

那么,我们只需要把虚线的长设置成圆的周长,在利用偏移stroke-dashoffset 就可以实现我们的饼图效果啦

这里计算周长公式就不说了,人尽皆知

<svg width="230px" height="230px">
  .....
    <circle r="100" cx="115" cy="115" stroke-width="12" stroke-dasharray="628" fill="transparent" stroke="url(#linearGradient)" />
  .....

最后我们在根据实际的数据 去生成 偏移值

计算: 偏移值 = 周长 - 周长 * 实际数据 这里得到计算 是38.93

<svg width="230px" height="230px">
  .....
    <circle r="100" cx="115" cy="115" stroke-width="12" stroke-dasharray="628" stroke-dashoffset="38.93" fill="transparent" stroke="url(#linearGradient)" />
  .....

最终代码

 <svg width="230px" height="230px">
    <defs>
      <linearGradient x1="40%" y1="15%" x2="90%" y2="80%" id="linearGradient">
        <stop offset="40%" stop-color='#29CABB' />
        <stop offset="90%" stop-color='#EBD178' />
      </linearGradient>
    </defs>
    <circle r="110" cx="115" cy="115" stroke-width="10" fill="transparent" stroke="#23aaff33" />
    <circle r="100" cx="115" cy="115" stroke-width="12" fill="transparent" stroke="url(#linearGradient)"  stroke-dasharray="628" stroke-dashoffset="38.93"/>
    <text fill="#ffffff" font-size="35" font-family="Verdana" x="58" y="100">
      93.8%</text>
    <text fill="#ffffff" font-size="32" font-family="Verdana" x="65" y="150">
        留存率</text>
  </svg>

到这里我们只用到5个标签 就能实现好看的饼图

2022-02-09-14-15-16.png

当然 一般的实际应用中,希望还是通过js去动态的计算stroke-dashoffset, 还可以添加上过渡效果

最后贴上完整的demo代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>svg-round</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      padding: 200px;
      background: #020C18;
    }
    #svgRound {
      transition: all 1s;
    }
  </style>
</head>
<body>
  <svg width="230px" height="230px">
    <defs>
      <linearGradient x1="40%" y1="15%" x2="90%" y2="80%" id="linearGradient">
        <stop offset="40%" stop-color='#29CABB' />
        <stop offset="90%" stop-color='#EBD178' />
      </linearGradient>
    </defs>
    <circle r="110" cx="115" cy="115" stroke-width="10" fill="transparent" stroke="#23aaff33" />
    <circle r="100" cx="115" cy="115" stroke-width="12" fill="transparent" stroke="url(#linearGradient)" id="svgRound"  stroke-dasharray="628" stroke-dashoffset="628"/>
    <text fill="#ffffff" font-size="35" font-family="Verdana" x="58" y="100">
      93.8%</text>
    <text fill="#ffffff" font-size="32" font-family="Verdana" x="65" y="150">
        留存率</text>
  </svg>
  <script>
    const svgRound = document.querySelector("#svgRound")
    setTimeout(() => {
      svgRound.style.strokeDashoffset = "30"
    }, 1000)
  </script>
</body>
</html>