大家好,我是设计师邱兴,一个学习前端的设计师,今天给大家制作一个用SVG实现的带刻度的仪表盘,SVG相较于E chart来说制作简单,但是效果可以非常丰富。
一、目标
通过SVG和JavaScript实现一个圆形仪表盘进度条,包含以下功能:
- 圆形上有20个色块,初始透明度为0.3。
- 使用滑块动态调整进度,根据进度值改变色块的透明度。
- 显示当前进度百分比和进度值。
二、所需工具与准备
- 工具 :
- 一个文本编辑器(如Notepad++、Hbuild等)。
- 浏览器(用于预览效果)。
- 基础准备 :
- 确保你对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轻松实现动态效果。希望这个教程对你有所帮助! 以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。
