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轻松实现动态效果。希望这个教程对你有所帮助! 以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。

相关推荐
设计师也学前端10 天前
SVG数据可视化组件基础教程9:自定义电池电量进度
前端·svg
设计师也学前端10 天前
SVG数据可视化组件基础教程8:自定义水波球
前端·svg
设计师也学前端12 天前
SVG数据可视化组件基础教程7:自定义柱状图
前端·svg
SuperherRo14 天前
Web攻防-XSS跨站&文件类型&功能逻辑&SVG&PDF&SWF&HTML&XML&PMessage&LocalStorage
xml·pdf·html·svg·localstorage·swf·pmessage
实习生小黄15 天前
使用psd.js将psd路径转成svg格式
前端·javascript·svg
设计师也学前端16 天前
SVG数据可视化组件基础教程6:翻牌倒计时
前端·svg
设计师也学前端20 天前
SVG数据可视化组件基础教程5:带指针连续进度的仪表盘
svg·数据可视化
设计师也学前端21 天前
SVG数据可视化组件基础教程4:连续进度的仪表盘
svg·数据可视化
微笑边缘的金元宝21 天前
svg实现3环进度图,可动态调节进度数值,(vue)
前端·javascript·vue.js·svg