我是设计师邱兴,一个学习前端的设计师,今天给大家制作一个用SVG实现的自定义电池电量进度,SVG相较于Echart来说制作简单,但是效果可以非常丰富。
一、目标
通过HTML、CSS和JavaScript创建一个动态的SVG电池电量展示,实现以下功能:
- 使用SVG绘制电池图标。
- 通过滑块动态调整和显示电池电量。
- 根据电量值自动改变电量条的颜色和文字颜色以提高可读性。
二、所需工具与准备
-
工具:
- 一个文本编辑器(如Notepad++、VS Code等)。
- 浏览器(用于预览效果)。
-
基础准备:
- 确保你对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电池电量展示。这个展示可以根据滑块的值动态更新电量条的宽度、颜色和文字颜色,从而直观地显示电池电量状态。你可以通过调整代码中的参数来改变电池图标的外观和行为。希望这个教程对你有所帮助!
以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。
