新闻中心
Chart.js 实现分组堆叠柱状图:数据转换与配置详解

本教程详细介绍了如何在 Chart.js 中创建分组堆叠柱状图。文章从理解 Chart.js 对数据结构的要求出发,逐步演示了如何将复杂的原始数据(包含设备、用户及其点数)转换为 Chart.js 可识别的格式。重点讲解了数据扁平化、类别识别以及数据集构建过程,并提供了完整的 Chart.js 配置代码,特别是堆叠选项的设置,旨在帮助开发者高效地实现此类复杂图表。
在数据可视化领域,分组堆叠柱状图是一种强大的工具,能够清晰地展示不同类别在多个分组下的构成和总和。Chart.js 作为一个流行的 J*aScript 图表库,提供了丰富的功能来实现这类图表。本文将深入探讨如何处理原始数据,并将其适配 Chart.js 的要求,最终呈现一个分组堆叠柱状图。
理解 Chart.js 对数据结构的要求
Chart.js 绘制柱状图时,通常需要两个核心部分:
- labels: 这代表图表的 X 轴标签,对于分组堆叠柱状图,它通常是每个“组”的名称(例如,设备名称)。
-
datasets: 这是一个数组,每个元素代表图表中的一个数据集。在堆叠柱状图中,每个数据集通常代表一个堆叠的“层”(例如,一个用户)。每个数据集对象包含:
- label: 数据集的名称(例如,用户名)。
- data: 一个数组,包含对应 labels 中每个分组的数据点。
- backgroundColor: 数据集的颜色。
原始数据结构分析
假设我们有以下原始数据,它描述了不同设备上各个用户的点数:
// 原始数据示例
const alldata = [
{
device: "Laptop",
values: [
{ amckinlay: '30' },
{ cvu: '150' }
]
},
{
device: "Phone",
values: [
{ amckinlay: '100' }
]
}
];这个数据结构的问题在于 values 数组中的每个对象是一个键值对,其键名(用户)是动态的,这使得直接提取和构建 Chart.js 所需的 datasets 变得困难。我们需要将其转换为更易于处理的扁平化结构。
数据预处理与转换
为了满足 Chart.js 的数据结构要求,我们需要对原始数据进行一系列转换。
1. 提取 X 轴标签(设备名称)
首先,从原始数据中提取所有唯一的设备名称,作为图表的 X 轴 labels。
BrandCrowd
一个在线Logo免费设计生成器
200
查看详情
const labels = alldata.map((x) => x.device); // 结果: ['Laptop', 'Phone']
2. 扁平化并标准化数据
将原始的嵌套结构转换为一个扁平化的数组,其中每个元素都包含 device、category(用户)和 value(点数)。
let transformedData = alldata
.map((x) =>
x.values.reduce((acc, cur) => {
for (let k in cur) {
acc.push({
device: x.device,
category: k, // 用户名
value: parseInt(cur[k], 10), // 点数,转换为数字
});
}
return acc;
}, [])
)
.flat();
/*
transformedData 结果示例:
[
{ device: 'Laptop', category: 'amckinlay', value: 30 },
{ device: 'Laptop', category: 'cvu', value: 150 },
{ device: 'Phone', category: 'amckinlay', value: 100 }
]
*/这里,我们使用 map 遍历每个设备,然后用 reduce 将其 values 数组中的键值对转换为标准的对象格式,最后用 flat() 将所有设备的数据扁平化到一个数组中。
3. 识别堆叠类别(用户名称)
从扁平化后的数据中提取所有唯一的 category(即用户名),这些将作为每个 dataset 的 label。
const subLabels = [...new Set(transformedData.map((x) => x.category))]; // 结果: ['amckinlay', 'cvu']
4. 构建 Chart.js 数据集 (datasets)
这是最关键的一步。我们需要遍历 subLabels(用户),为每个用户创建一个 dataset 对象。每个 dataset 的 data 数组应该包含该用户在所有设备上的点数,如果某个用户在某个设备上没有数据,则填入 0。同时,定义每个类别的背景颜色。
// 定义每个类别的颜色设置
const colorSettings = [
{
category: 'amckinlay',
backgroundColor: 'rgba(75, 192, 192, 0.6)',
},
{
category: 'cvu',
backgroundColor: 'rgba(255, 99, 132, 0.6)',
},
// 可以添加更多类别和颜色
];
const datasets = subLabels.reduce((acc, currentCategory) => {
const categoryData = [];
for (let device of labels) {
// 查找当前类别(用户)在当前设备上的值,如果没有则为0
const value =
transformedData.find(
(x) => x.device === device && x.category === currentCategory
)?.value ?? 0;
categoryData.push(value);
}
// 获取当前类别的颜色
const color = colorSettings.find((x) => x.category === currentCategory)
?.backgroundColor;
acc.push({
label: currentCategory,
data: categoryData,
backgroundColor: color,
});
return acc;
}, []);
/*
datasets 结果示例:
[
{
label: 'amckinlay',
data: [30, 100], // 'Laptop' 30, 'Phone' 100
backgroundColor: 'rgba(75, 192, 192, 0.6)'
},
{
label: 'cvu',
data: [150, 0], // 'Laptop' 150, 'Phone' 0
backgroundColor: 'rgba(255, 99, 132, 0.6)'
}
]
*/Chart.js 配置
数据准备就绪后,就可以配置 Chart.js 来绘制图表了。关键在于设置 options.scales.x.stacked 和 options.scales.y.stacked 为 true,以启用堆叠功能。
<!DOCTYPE html>
<html>
<head>
<title>Chart.js 分组堆叠柱状图</title>
<s
cript src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
#myChart {
max-width: 800px;
margin: 20px auto;
}
</style>
</head>
<body>
<canvas id="myChart"></canvas>
<script>
// 原始数据
const alldata = [
{
device: "Laptop",
values: [
{ amckinlay: '30' },
{ cvu: '150' }
]
},
{
device: "Phone",
values: [
{ amckinlay: '100' }
]
}
];
// 1. 提取 X 轴标签(设备名称)
const labels = alldata.map((x) => x.device);
// 2. 扁平化并标准化数据
let transformedData = alldata
.map((x) =>
x.values.reduce((acc, cur) => {
for (let k in cur) {
acc.push({
device: x.device,
category: k,
value: parseInt(cur[k], 10),
});
}
return acc;
}, [])
)
.flat();
// 3. 识别堆叠类别(用户名称)
const subLabels = [...new Set(transformedData.map((x) => x.category))];
// 定义每个类别的颜色设置
const colorSettings = [
{
category: 'amckinlay',
backgroundColor: 'rgba(75, 192, 192, 0.6)',
},
{
category: 'cvu',
backgroundColor: 'rgba(255, 99, 132, 0.6)',
},
];
// 4. 构建 Chart.js 数据集 (datasets)
const datasets = subLabels.reduce((acc, currentCategory) => {
const categoryData = [];
for (let device of labels) {
const value =
transformedData.find(
(x) => x.device === device && x.category === currentCategory
)?.value ?? 0;
categoryData.push(value);
}
const color = colorSettings.find((x) => x.category === currentCategory)
?.backgroundColor;
acc.push({
label: currentCategory,
data: categoryData,
backgroundColor: color,
});
return acc;
}, []);
// Chart.js 实例化
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar', // 图表类型为柱状图
data: {
labels: labels, // X 轴标签
datasets: datasets, // 数据集
},
options: {
responsive: true, // 响应式布局
scales: {
x: {
stacked: true, // X 轴堆叠
},
y: {
stacked: true, // Y 轴堆叠
beginAtZero: true // Y 轴从0开始
},
},
plugins: {
title: {
display: true,
text: '设备用户点数分组堆叠柱状图'
}
}
},
});
</script>
</body>
</html>注意事项
- 数据完整性: 确保所有可能的类别在 colorSettings 中都有对应的颜色定义,以避免图表样式缺失。
- 零值处理: 在构建 datasets 时,对于某个类别在特定分组下没有数据的情况,我们将其值设置为 0。这是确保 data 数组长度与 labels 匹配,并正确显示堆叠图的关键。
- 响应式设计: responsive: true 选项可以使图表在容器大小变化时自动调整。
- 数据类型: 确保所有数值数据都已正确转换为数字类型,例如使用 parseInt() 或 parseFloat()。
总结
通过上述步骤,我们成功地将复杂的原始数据转换为 Chart.js 所需的格式,并配置了一个功能完善的分组堆叠柱状图。核心在于理解 Chart.js 的数据模型,并通过数据转换逻辑将原始数据适配到这个模型中。掌握数据预处理和 Chart.js 配置中的 stacked 选项,是实现此类高级图表的关键。
以上就是Chart.js 实现分组堆叠柱状图:数据转换与配置详解的详细内容,更多请关注其它相关文章!
# 扁平化
# 云南seo网络优化教程
# 购物网站推广
# 推广seo网站企业
# seo排名关键词排名怎么排
# 网站对seo影响吗
# 云速推网站优化咨询热线
# seo上词报价
# 传媒网站推广怎么做的
# 免费学习抖音seo
# 吴川seo快速优化软件
# 组中
# 遍历
# 这是
# 键值
# 将其
# javascript
# 原始数据
# 转换为
# 柱状图
# 数据结构
# 键值对
# 响应式设计
# 响应式布局
# 数据可视化
# cdn
# 工具
# npm
# go
# js
# html
# java
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
机构:以往存储涨价周期小米利润率实际上有所改善 能转嫁给消费者等
12306选座怎么选到特殊座位_12306特殊座位选择注意事项
如何优雅地解决Livewire文件上传难题?SpatieLivewireFilepond让一切变得简单
理解Python模块与全局变量的作用域管理
126邮箱账号注册 电脑版登录入口
win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】
1688商家版怎样分析买家画像精准供货_1688商家版分析买家画像精准供货【供货策略】
高德地图总提示网络异常怎么办 高德地图离线导航设置与网络排查方法
J*a里如何使用N*igableMap进行导航操作_可导航Map操作技巧解析
2025-2030年全球乘用车销量预测:新能源成增长主力
b站如何看历史记录_b站观看历史找回方法
如何仅使用CSS更改登录界面背景图像图标的颜色
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售
192.168.1.1管理中心入口 192.168.1.1路由器网页设置平台
css链接悬停下划线样式如何自定义_使用::after结合content和transition
Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量
AO3官方在线访问地址 Archive of Our Own最新镜像合集
《马克思佩恩3》早期版本曝光 UI设计曾多次调整!
Django表单验证失败时保留用户输入数据的最佳实践
J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析
怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】
J*a里如何实现订单支付与库存同步功能_支付库存同步项目开发方法说明
三星ZFold5多任务卡顿_Samsung ZFold5流畅度提升
Python自定义类排序:解决lambda键值访问TypeError的实践指南
怎样更改Windows系统的默认安装路径_避免C盘爆满的终极设置【技巧】
j*a toString()的覆盖
C++ string find函数返回值npos详解_C++字符串查找失败的判断条件
J*a TimerTask中HashMap意外清空的深层原因与解决方案
《北京人工智能产业白皮书(2025)》发布:全年核心产值预计突破 4500 亿元
今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程
QQ邮箱官方网页版登录 QQ邮箱个人邮箱快速访问
在Go Martini框架中高效服务动态生成图像的实践指南
Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】
QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台
利用Bokeh CustomJS动态控制DataTable列可见性
高德地图怎么看全景照片_高德地图全景照片浏览教程
反效果?《战地6》免费试玩开启后玩家数不升反降
神庙逃亡小游戏在线玩 神庙逃亡小游戏入口
如何有效阻止外部脚本意外修改内联样式的高度属性
Mac怎么查看崩溃日志_Mac控制台错误报告分析
漫蛙网页登录入口 漫蛙漫画官方授权网址
qq游戏手机版下载安装_qq游戏移动端入口
照顾宝贝2小游戏免费秒玩入口
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
CSS布局:解决全屏元素100%尺寸与外边距导致的页面溢出问题
mcjs网页版在线存档 mcjs云存档登录入口
微信怎么把收藏的内容分类管理 微信收藏内容标签分类方法
现代化 SciPy 一维插值:interp1d 的替代方案与最佳实践
如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!


2025-11-06
浏览次数:次
返回列表
cript src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
#myChart {
max-width: 800px;
margin: 20px auto;
}
</style>
</head>
<body>
<canvas id="myChart"></canvas>
<script>
// 原始数据
const alldata = [
{
device: "Laptop",
values: [
{ amckinlay: '30' },
{ cvu: '150' }
]
},
{
device: "Phone",
values: [
{ amckinlay: '100' }
]
}
];
// 1. 提取 X 轴标签(设备名称)
const labels = alldata.map((x) => x.device);
// 2. 扁平化并标准化数据
let transformedData = alldata
.map((x) =>
x.values.reduce((acc, cur) => {
for (let k in cur) {
acc.push({
device: x.device,
category: k,
value: parseInt(cur[k], 10),
});
}
return acc;
}, [])
)
.flat();
// 3. 识别堆叠类别(用户名称)
const subLabels = [...new Set(transformedData.map((x) => x.category))];
// 定义每个类别的颜色设置
const colorSettings = [
{
category: 'amckinlay',
backgroundColor: 'rgba(75, 192, 192, 0.6)',
},
{
category: 'cvu',
backgroundColor: 'rgba(255, 99, 132, 0.6)',
},
];
// 4. 构建 Chart.js 数据集 (datasets)
const datasets = subLabels.reduce((acc, currentCategory) => {
const categoryData = [];
for (let device of labels) {
const value =
transformedData.find(
(x) => x.device === device && x.category === currentCategory
)?.value ?? 0;
categoryData.push(value);
}
const color = colorSettings.find((x) => x.category === currentCategory)
?.backgroundColor;
acc.push({
label: currentCategory,
data: categoryData,
backgroundColor: color,
});
return acc;
}, []);
// Chart.js 实例化
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar', // 图表类型为柱状图
data: {
labels: labels, // X 轴标签
datasets: datasets, // 数据集
},
options: {
responsive: true, // 响应式布局
scales: {
x: {
stacked: true, // X 轴堆叠
},
y: {
stacked: true, // Y 轴堆叠
beginAtZero: true // Y 轴从0开始
},
},
plugins: {
title: {
display: true,
text: '设备用户点数分组堆叠柱状图'
}
}
},
});
</script>
</body>
</html>