SVG数据可视化组件基础教程9:自定义电池电量进度

我是设计师邱兴,一个学习前端的设计师,今天给大家制作一个用SVG实现的自定义电池电量进度,SVG相较于Echart来说制作简单,但是效果可以非常丰富。

一、目标

通过HTML、CSS和JavaScript创建一个动态的SVG电池电量展示,实现以下功能:

  1. 使用SVG绘制电池图标。
  2. 通过滑块动态调整和显示电池电量。
  3. 根据电量值自动改变电量条的颜色和文字颜色以提高可读性。

二、所需工具与准备

  1. 工具

    • 一个文本编辑器(如Notepad++、VS Code等)。
    • 浏览器(用于预览效果)。
  2. 基础准备

    • 确保你对HTML、CSS和JavaScript有一定的了解。
    • 确保你对SVG的基本语法有一定了解。

三、代码分析与操作步骤

1. 创建HTML结构

创建一个HTML文件(如Lesson9.html)并设置基本的HTML结构:

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 电池电量展示</title>
  <style>
    /* 样式部分 */
  </style>
</head>
<body>
  <div class="container">
    <h1>电池电量监控</h1>
    <div class="battery-container">
      <svg id="battery" width="200" height="100" viewBox="0 0 200 100">
        <!-- 电池外壳 -->
        <rect x="1" y="1" width="180" height="98" rx="10" ry="10"
              fill="none" stroke="#333" stroke-width="2"/>
        <!-- 电池正极 -->
        <rect x="181" y="25" width="15" height="50" rx="5" ry="5"
              fill="#333"/>
        
        <!-- 电量区域的剪切蒙版 -->
        <defs>
          <clipPath id="charge-clip">
            <rect id="clip-rect" x="6" y="6" width="169" height="88" rx="5" ry="5" />
          </clipPath>
        </defs>

        <!-- 电量条 -->
        <g clip-path="url(#charge-clip)">
          <rect id="charge-level" x="6" y="6" width="0" height="88" />
        </g>

        <!-- 电量文字 -->
        <text id="level-text" x="90" y="60" text-anchor="middle"
              font-size="28" font-weight="bold" fill="#333">0%</text>
      </svg>
    </div>
    <div class="slider-container">
      <input type="range" id="level-slider" min="0" max="100" value="75" />
      <label id="level-label" for="level-slider">当前电量: 75%</label>
    </div>
  </div>

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

2. 添加CSS样式

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

css 复制代码
body {
  background: #f0f4f8; /* 淡雅的背景色 */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.container {
  background: white;
  border-radius: 20px;
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
  padding: 40px;
  text-align: center;
  width: 350px;
}
h1 {
  color: #333;
  margin-top: 0;
  margin-bottom: 30px;
  font-weight: 600;
}
.battery-container {
  margin-bottom: 30px;
}
.slider-container {
  width: 100%;
}
input[type="range"] {
  width: 80%;
  cursor: pointer;
}
#level-label {
  font-size: 18px;
  color: #555;
  font-weight: 500;
  margin-top: 15px;
  display: block;
}
  • body :设置页面背景为淡雅的蓝色,使用flexbox布局使内容居中。
  • .container:设置容器的背景、圆角、阴影和内边距。
  • .battery-container:设置电池图标的外边距。
  • .slider-container:设置滑块容器的宽度。
  • input[type="range"] :设置滑块的宽度和游标样式。
  • #level-label:设置电量标签的字体大小、颜色和边距。

3. 编写JavaScript代码

<script>标签中,添加以下JavaScript代码来实现动态调整电池电量的功能:

ini 复制代码
const slider = document.getElementById('level-slider');
const chargeLevelRect = document.getElementById('charge-level');
const levelText = document.getElementById('level-text');
const levelLabel = document.getElementById('level-label');

const maxChargeWidth = 169; // 电量条最大宽度 (180 - 5*2 - 1)

const colors = {
  low: '#ef5350',       // 红色
  medium: '#ffab00',    // 橙色
  high: '#26a69a'       // 绿色
};

function updateBattery(level) {
  // 1. 更新电量条宽度
  const chargeWidth = (level / 100) * maxChargeWidth;
  chargeLevelRect.setAttribute('width', chargeWidth);

  // 2. 更新颜色
  let color;
  if (level <= 20) {
    color = colors.low;
  } else if (level <= 50) {
    color = colors.medium;
  } else {
    color = colors.high;
  }
  chargeLevelRect.setAttribute('fill', color);

  // 3. 更新文本
  levelText.textContent = `${level}%`;
  levelLabel.textContent = `当前电量: ${level}%`;

  // 4. 调整文字颜色以获得更好的对比度
  if (chargeWidth > levelText.getBBox().width / 2 + 10) {
    levelText.style.fill = '#fff';
  } else {
    levelText.style.fill = '#333';
  }
}

// 事件监听
slider.addEventListener('input', (e) => {
  const newLevel = parseInt(e.target.value, 10);
  updateBattery(newLevel);
});

// 初始化
updateBattery(parseInt(slider.value, 10));

4. 关键参数说明

  • maxChargeWidth:电量条的最大宽度,计算方式为电池外壳宽度减去内边距和边框宽度。
  • colors:定义了不同电量区间的颜色,低电量(红色)、中电量(橙色)、高电量(绿色)。
  • level:当前电量值,范围为0到100。
  • chargeWidth:根据当前电量值计算的电量条宽度。
  • color:根据当前电量值选择的颜色。

5. 完整代码

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

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 电池电量展示</title>
  <style>
    body {
      background: #f0f4f8; /* 淡雅的背景色 */
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    }
    .container {
      background: white;
      border-radius: 20px;
      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
      padding: 40px;
      text-align: center;
      width: 350px;
    }
    h1 {
      color: #333;
      margin-top: 0;
      margin-bottom: 30px;
      font-weight: 600;
    }
    .battery-container {
      margin-bottom: 30px;
    }
    .slider-container {
      width: 100%;
    }
    input[type="range"] {
      width: 80%;
      cursor: pointer;
    }
    #level-label {
      font-size: 18px;
      color: #555;
      font-weight: 500;
      margin-top: 15px;
      display: block;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>电池电量监控</h1>
    <div class="battery-container">
      <svg id="battery" width="200" height="100" viewBox="0 0 200 100">
        <!-- 电池外壳 -->
        <rect x="1" y="1" width="180" height="98" rx="10" ry="10"
              fill="none" stroke="#333" stroke-width="2"/>
        <!-- 电池正极 -->
        <rect x="181" y="25" width="15" height="50" rx="5" ry="5"
              fill="#333"/>
        
        <!-- 电量区域的剪切蒙版 -->
        <defs>
          <clipPath id="charge-clip">
            <rect id="clip-rect" x="6" y="6" width="169" height="88" rx="5" ry="5" />
          </clipPath>
        </defs>

        <!-- 电量条 -->
        <g clip-path="url(#charge-clip)">
          <rect id="charge-level" x="6" y="6" width="0" height="88" />
        </g>

        <!-- 电量文字 -->
        <text id="level-text" x="90" y="60" text-anchor="middle"
              font-size="28" font-weight="bold" fill="#333">0%</text>
      </svg>
    </div>
    <div class="slider-container">
      <input type="range" id="level-slider" min="0" max="100" value="75" />
      <label id="level-label" for="level-slider">当前电量: 75%</label>
    </div>
  </div>

  <script>
    const slider = document.getElementById('level-slider');
    const chargeLevelRect = document.getElementById('charge-level');
    const levelText = document.getElementById('level-text');
    const levelLabel = document.getElementById('level-label');

    const maxChargeWidth = 169; // 电量条最大宽度 (180 - 5*2 - 1)

    const colors = {
      low: '#ef5350',       // 红色
      medium: '#ffab00',    // 橙色
      high: '#26a69a'       // 绿色
    };

    function updateBattery(level) {
      // 1. 更新电量条宽度
      const chargeWidth = (level / 100) * maxChargeWidth;
      chargeLevelRect.setAttribute('width', chargeWidth);

      // 2. 更新颜色
      let color;
      if (level <= 20) {
        color = colors.low;
      } else if (level <= 50) {
        color = colors.medium;
      } else {
        color = colors.high;
      }
      chargeLevelRect.setAttribute('fill', color);

      // 3. 更新文本
      levelText.textContent = `${level}%`;
      levelLabel.textContent = `当前电量: ${level}%`;

      // 4. 调整文字颜色以获得更好的对比度
      if (chargeWidth > levelText.getBBox().width / 2 + 10) {
        levelText.style.fill = '#fff';
      } else {
        levelText.style.fill = '#333';
      }
    }

    // 事件监听
    slider.addEventListener('input', (e) => {
      const newLevel = parseInt(e.target.value, 10);
      updateBattery(newLevel);
    });

    // 初始化
    updateBattery(parseInt(slider.value, 10));
  </script>
</body>
</html>

四、总结

通过以上步骤,你可以创建一个动态的SVG电池电量展示。这个展示可以根据滑块的值动态更新电量条的宽度、颜色和文字颜色,从而直观地显示电池电量状态。你可以通过调整代码中的参数来改变电池图标的外观和行为。希望这个教程对你有所帮助!

以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。

相关推荐
OEC小胖胖4 小时前
去中心化身份:2025年Web3身份验证系统开发实践
前端·web3·去中心化·区块链
vvilkim5 小时前
Electron 进程间通信(IPC)深度优化指南
前端·javascript·electron
ai小鬼头7 小时前
百度秒搭发布:无代码编程如何让普通人轻松打造AI应用?
前端·后端·github
漂流瓶jz7 小时前
清除浮动/避开margin折叠:前端CSS中BFC的特点与限制
前端·css·面试
前端 贾公子7 小时前
在移动端使用 Tailwind CSS (uniapp)
前端·uni-app
散步去海边7 小时前
Cursor 进阶使用教程
前端·ai编程·cursor
清幽竹客7 小时前
vue-30(理解 Nuxt.js 目录结构)
前端·javascript·vue.js
weiweiweb8887 小时前
cesium加载Draco几何压缩数据
前端·javascript·vue.js
幼儿园技术家7 小时前
微信小店与微信小程序简单集成指南
前端
我不吃饼干9 天前
鸽了六年的某大厂面试题:你会手写一个模板引擎吗?
前端·javascript·面试