SVG数据可视化组件基础教程:带刻度的仪表盘

大家好,我是设计师邱兴,一个学习前端的设计师,今天给大家制作一个用SVG实现的带刻度的仪表盘,SVG相较于E chart来说制作简单,但是效果可以非常丰富。

一、目标

通过SVG和JavaScript实现一个圆形仪表盘进度条,包含以下功能:

  1. 圆形上有20个色块,初始透明度为0.3。
  2. 使用滑块动态调整进度,根据进度值改变色块的透明度。
  3. 显示当前进度百分比和进度值。

二、所需工具与准备

  1. 工具
    • 一个文本编辑器(如Notepad++、Hbuild等)。
    • 浏览器(用于预览效果)。
  2. 基础准备
    • 确保你对HTML、CSS和JavaScript有一定的了解。
    • 确保你对SVG的基本语法有一定了解。

三、代码分析与操作步骤

1. 创建HTML结构

首先,创建一个HTML文件,并设置基本的HTML结构:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 带刻度的仪表盘</title>
  <style>
    /* 样式部分 */
  </style>
</head>
<body>
  <!-- SVG带刻度的仪表盘 -->
  <div class="gauge-container">
    <svg id="gauge" width="320" height="320" viewBox="0 0 320 320">
      <!-- 色块组 -->
      <g id="blocks"></g>
      <!-- 中心圆形装饰 -->
      <circle cx="160" cy="160" r="90" fill="#fff"/>
      <!-- 进度文本 -->
      <text id="progressText" x="160" y="175" text-anchor="middle" font-size="48" fill="#333" font-weight="bold">0%</text>
    </svg>
  </div>
  <!-- 滑块容器 -->
  <div class="slider-container">
    <input type="range" id="progressSlider" min="0" max="20" value="0" />
    <div>进度:<span id="progressNum">0</span>/20</div>
  </div>

  <script>
    // JavaScript部分
  </script>
</body>
</html>

2. 添加CSS样式

<style>标签中,添加以下CSS样式:

css 复制代码
body {
  background: #f8f8f8;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: Arial, sans-serif;
}
.gauge-container {
  margin-top: 40px;
  margin-bottom: 20px;
}
.progress-value {
  font-size: 2em;
  font-weight: bold;
  text-align: center;
  margin-top: -60px;
  color: #333;
  user-select: none;
}
.slider-container {
  margin-top: 30px;
  text-align: center;
}
  • 设置页面背景颜色为#f8f8f8
  • 使用flexbox布局将SVG仪表盘和滑块居中显示。
  • 设置进度文本和滑块的样式。

3. 绘制SVG色块

<script>标签中,使用JavaScript动态生成20个色块:

javascript 复制代码
const totalBlocks = 20; // 色块总数
const radius = 120; // 圆的半径
const centerX = 160; // 圆心X坐标
const centerY = 160; // 圆心Y坐标
const blockWidth = 24; // 色块宽度
const blockHeight = 32; // 色块高度
const blockOpacity = 0.3; // 初始透明度
const blockColor = "#ff5722"; // 色块颜色

const blocksGroup = document.getElementById('blocks'); // 获取色块组

// 生成色块
for (let i = 0; i < totalBlocks; i++) {
  const angle = (i / totalBlocks) * 2 * Math.PI - Math.PI / 2; // 计算每个色块的角度
  const x = centerX + radius * Math.cos(angle) - blockWidth / 2; // 计算色块的X坐标
  const y = centerY + radius * Math.sin(angle) - blockHeight / 2; // 计算色块的Y坐标
  const rotate = (angle * 180 / Math.PI) + 90; // 计算旋转角度

  const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); // 创建SVG矩形元素
  rect.setAttribute("x", x);
  rect.setAttribute("y", y);
  rect.setAttribute("width", blockWidth);
  rect.setAttribute("height", blockHeight);
  rect.setAttribute("rx", 8); // 设置圆角
  rect.setAttribute("fill", blockColor);
  rect.setAttribute("opacity", blockOpacity);
  rect.setAttribute("transform", `rotate(${rotate} ${x + blockWidth/2} ${y + blockHeight/2})`); // 设置旋转
  rect.setAttribute("id", `block${i}`); // 设置ID
  blocksGroup.appendChild(rect); // 将色块添加到SVG中
}

4. 动态更新进度

<script>标签中,添加以下JavaScript代码来控制进度:

javascript 复制代码
// 控制进度
function setProgress(val) {
  for (let i = 0; i < totalBlocks; i++) {
    const rect = document.getElementById(`block${i}`); // 获取每个色块
    rect.setAttribute("opacity", i < val ? 1 : blockOpacity); // 根据进度值改变透明度
  }
  document.getElementById('progressText').textContent = Math.round(val / totalBlocks * 100) + "%"; // 更新进度文本
  document.getElementById('progressNum').textContent = val; // 更新进度值
}

// 监听滑块
document.getElementById('progressSlider').addEventListener('input', function() {
  setProgress(Number(this.value)); // 根据滑块值更新进度
});

// 初始化
setProgress(0); // 初始进度为0

5. 完整代码

将上述代码整合到一个HTML文件中,完整的代码如下:

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 带刻度的仪表盘</title>
  <style>
    body {
      background: #f8f8f8;
      display: flex;
      flex-direction: column;
      align-items: center;
      font-family: Arial, sans-serif;
    }
    .gauge-container {
      margin-top: 40px;
      margin-bottom: 20px;
    }
    .progress-value {
      font-size: 2em;
      font-weight: bold;
      text-align: center;
      margin-top: -60px;
      color: #333;
      user-select: none;
    }
    .slider-container {
      margin-top: 30px;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="gauge-container">
    <svg id="gauge" width="320" height="320" viewBox="0 0 320 320">
      <g id="blocks"></g>
      <circle cx="160" cy="160" r="90" fill="#fff"/>
      <text id="progressText" x="160" y="175" text-anchor="middle" font-size="48" fill="#333" font-weight="bold">0%</text>
    </svg>
  </div>
  <div class="slider-container">
    <input type="range" id="progressSlider" min="0" max="20" value="0" />
    <div>进度:<span id="progressNum">0</span>/20</div>
  </div>

  <script>
    const totalBlocks = 20;
    const radius = 120;
    const centerX = 160;
    const centerY = 160;
    const blockWidth = 24;
    const blockHeight = 32;
    const blockOpacity = 0.3;
    const blockColor = "#ff5722";

    const blocksGroup = document.getElementById('blocks');
    // 生成色块
    for (let i = 0; i < totalBlocks; i++) {
      const angle = (i / totalBlocks) * 2 * Math.PI - Math.PI / 2;
      const x = centerX + radius * Math.cos(angle) - blockWidth / 2;
      const y = centerY + radius * Math.sin(angle) - blockHeight / 2;
      const rotate = (angle * 180 / Math.PI) + 90;
      const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
      rect.setAttribute("x", x);
      rect.setAttribute("y", y);
      rect.setAttribute("width", blockWidth);
      rect.setAttribute("height", blockHeight);
      rect.setAttribute("rx", 8);
      rect.setAttribute("fill", blockColor);
      rect.setAttribute("opacity", blockOpacity);
      rect.setAttribute("transform", `rotate(${rotate} ${x + blockWidth/2} ${y + blockHeight/2})`);
      rect.setAttribute("id", `block${i}`);
      blocksGroup.appendChild(rect);
    }

    // 控制进度
    function setProgress(val) {
      for (let i = 0; i < totalBlocks; i++) {
        const rect = document.getElementById(`block${i}`);
        rect.setAttribute("opacity", i < val ? 1 : blockOpacity);
      }
      document.getElementById('progressText').textContent = Math.round(val / totalBlocks * 100) + "%";
      document.getElementById('progressNum').textContent = val;
    }

    // 监听滑块
    document.getElementById('progressSlider').addEventListener('input', function() {
      setProgress(Number(this.value));
    });

    // 初始化
    setProgress(0);
  </script>
</body>
</html>

五、总结

通过以上步骤,你可以使用SVG创建一个简单的带刻度的仪表盘。SVG的优势在于其矢量特性,可以无损放大,并且可以通过CSS和JavaScript轻松实现动态效果。希望这个教程对你有所帮助! 以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。

相关推荐
E_ICEBLUE23 天前
PPT 批量转图片:在 Web 预览中实现翻页效果(C#/VB.NET)
c#·powerpoint·svg
Highcharts.js23 天前
如何使用Highcharts SVG渲染器?
开发语言·javascript·python·svg·highcharts·渲染器
谜亚星2 个月前
SVG学习(五)
前端·svg
harrain2 个月前
前端svg精微操作局部动态改变呈现工程网架状态程度可视播放效果
前端·svg·工程网架图
我真的叫奥运2 个月前
scss mixin svg 颜色控制 以及与 png 方案对比讨论
前端·svg
harrain2 个月前
html里引入使用svg的方法
前端·svg
咬人喵喵2 个月前
SVG 答题类互动模板汇总(共 16 种/来自 E2 编辑器)
编辑器·svg·e2 编辑器
咬人喵喵2 个月前
16 类春节核心 SVG 交互方案拆解(E2 编辑器实战)
前端·css·编辑器·交互·svg
李少兄2 个月前
简单讲讲 SVG:前端开发中的矢量图形
前端·svg
咬人喵喵2 个月前
文生图:AI 是怎么把文字变成画的?
人工智能·编辑器·svg