Chart.js堆积的条形图-按值对条形中的值进行排序 [英] Chart.js stacked bar chart - sorting values in bar by value

查看:83
本文介绍了Chart.js堆积的条形图-按值对条形中的值进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用Chart.js框架(版本2.7)实现堆积的条形图,但遇到以下问题:在每个条形图中均以与JSON结构中提供的顺序相同的顺序绘制单个数据元素(这绝对合乎逻辑并且可以理解) .我希望对它们进行排序:最大的元素在栏的底部,最小的元素在栏的顶部.

I try to implement a stacked bar chart using Chart.js framework (version 2.7) und faced following problem: single data elements are drawn in each bar in the same order as provided in JSON structure (which is absolutely logical and understandable). I would like to have them sorted: biggest elements at the bottom of the bar, smallest at its top.

我想可以使用一些插件定制的黑魔法来实现它,但无法弄清楚.

I suppose it can be accomplished using some plugin customization black magic but can not figure it out.

任何帮助将不胜感激.

示例:

var chart = new Chart(document.getElementById('canvas'), {
				type : 'bar',
				data : {
					labels : ["2018-07-06", "2018-07-07", "2018-07-08", "2018-07-09", "2018-07-10"],
					datasets : [
						{
							label: "Dataset 1", 
							backgroundColor: "red", 
							data: [ {x: "2018-07-06", y: 1}, {x: "2018-07-07", y: 2}, {x: "2018-07-08", y: 3}]
						}, 
						{
							label: "Dataset 2", 
							backgroundColor: "blue", 
							data: [ {x: "2018-07-06", y: 3}, {x: "2018-07-07", y: 2}, {x: "2018-07-08", y: 1}]
						}, 
						{
							label: "Dataset 3", 
							backgroundColor: "green", 
							data: [ {x: "2018-07-06", y: 2}, {x: "2018-07-07", y: 1}, {x: "2018-07-08", y: 2}]
						}
					],
					borderWidth : 1
				},
				options : {
					responsive : true,
					maintainAspectRatio : false,
					title : {
						display : true,
						text : 'Test'
					},
					scales : {
						xAxes : [ {
							stacked : true,
							time : {
								unit : 'day'
							}
						} ],
						yAxes : [ {
							stacked : true,
							ticks : {
								beginAtZero : true
							}
						} ]
					}
				}
			});

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="canvas" height="500" width="500"></canvas>

在此示例中,我希望每一列的颜色顺序相反: 第一个蓝绿色红色,
红-蓝-绿或蓝-红-绿,秒 红绿蓝三色.

In this example I would like to have order of colors in each column inversed: blue-green-red in first one,
red-blue-green or blue-red-green in second, red-green-blue in the third.

推荐答案

可能可以通过某种方式更有效和/或更漂亮地完成,但是我必须自己解决.

Probably it could be done somehow more efficient and / or beautiful, but I had to solve it on my own.

/*
* chart.js do not support stacked bar charts, which are sorted by value,
* therefore it's needed to perform this functionality with custom plugins
*/
Chart.plugins.register({

/*
* Sorts data by value and calculates values for bar stacks
*/
beforeDraw(chart) {

	// create data container in chart instance
	chart.sortedData = {};
	
	// iterate over datasets
	chart.data.datasets.forEach((dataset, datasetIndex) => {
	
		// iterate over dataset records
		dataset.data.forEach((data, index) => {
		
			// create data container for bar stack data
			if(!chart.sortedData[index]) {
				chart.sortedData[index] = {
					data: []
				};
			}
			
			// save data
			chart.sortedData[index].data[datasetIndex] = {
				datasetIndex: datasetIndex,
				hidden: chart.getDatasetMeta(datasetIndex).hidden ? true : false,
				color: dataset.backgroundColor,
				value: dataset.data[index].y,
				y: chart.getDatasetMeta(datasetIndex).data[index]._model.y,
				base: chart.getDatasetMeta(datasetIndex).data[index]._model.base,
			};
			
		});
	});
	
	var chartTop = chart.scales['y-axis-0'].top;
	var max = chart.scales['y-axis-0'].max;
	var h = chart.scales['y-axis-0'].height / max;
	
	// iterate over datasets
	chart.data.datasets.forEach((dataset, datasetIndex) => {
		
		// iterate over dataset records
		dataset.data.forEach((data, index) => {
		
			// sort data in bar stack by value
			chart.sortedData[index].data = Object.keys(chart.sortedData[index].data)
				.map(k => chart.sortedData[index].data[k])
				.sort((a, b) => a.value - b.value);
				
			// iterate over stack records
			chart.sortedData[index].data.forEach((d, i) => {
			
				// calculate base value
				d.base = chartTop + (max - Object.keys(chart.sortedData[index].data)
					.map(k => chart.sortedData[index].data[k].value)
					.reduce((a, b) => a + b, 0)) * h
					+ Object.keys(chart.sortedData[index].data)
					.map(k => chart.sortedData[index].data[k])
					.filter(d => d.hidden)
					.reduce((a, b) => a + b.value, 0) * h;					
				
				// increase base value with values of previous records
				for (var j = 0; j < i; j++) {
					d.base += chart.sortedData[index].data[j].hidden 
						? 0 
						: h * chart.sortedData[index].data[j].value;
				}
				
				// set y value
				d.y = d.base + h * d.value;
				
			});
		});
	});
},

/*
* Sets values for base and y
*/
beforeDatasetDraw(chart, args) {
	chart.getDatasetMeta(args.index).data.forEach((data, index) => {
		var el = chart.sortedData[index].data.filter(e => e.datasetIndex === args.index)[0];
		data._model.y = el.y;
		data._model.base = el.base;
	});
   }
   
});

var chart = new Chart(document.getElementById('canvas'), {
				type : 'bar',
				data : {
					labels : ["2018-07-06", "2018-07-07", "2018-07-08", "2018-07-09", "2018-07-10"],
					datasets : [
						{
							label: "Dataset 1", 
							backgroundColor: "red", 
							data: [ {x: "2018-07-06", y: 1}, {x: "2018-07-07", y: 2}, {x: "2018-07-08", y: 3}]
						}, 
						{
							label: "Dataset 2", 
							backgroundColor: "blue", 
							data: [ {x: "2018-07-06", y: 3}, {x: "2018-07-07", y: 2}, {x: "2018-07-08", y: 1}]
						}, 
						{
							label: "Dataset 3", 
							backgroundColor: "green", 
							data: [ {x: "2018-07-06", y: 2}, {x: "2018-07-07", y: 1}, {x: "2018-07-08", y: 2}]
						}
					],
					borderWidth : 1
				},
				options : {
					responsive : true,
					maintainAspectRatio : false,
					title : {
						display : true,
						text : 'Test'
					},
					scales : {
						xAxes : [ {
							stacked : true,
							time : {
								unit : 'day'
							}
						} ],
						yAxes : [ {
							stacked : true,
							ticks : {
								beginAtZero : true
							}
						} ]
					}
				}
			});

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="canvas" height="500" width="500"></canvas>

这篇关于Chart.js堆积的条形图-按值对条形中的值进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆