使用类似this one的条形图,可以更改条形的宽度以表示另一个数据属性,例如水果的重量。水果越重,酒吧越厚。
您使用脚本here。我对其他javascript绘图库开放,只要它们是免费的,就可以这样做。
$(function () {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: 'Column chart with negative values'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
tooltip: {
formatter: function() {
return ''+
this.series.name +': '+ this.y +'';
}
},
credits: {
enabled: false
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
// I would like something like this (3.5, 6 etc is the width) :
// data: [[5, 3.4], [3, 6], [4, 3.4], [7, 2], [2, 5]]
}, {
name: 'Jane',
data: [2, -2, -3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, -2, 5]
}]
});
});
});
答案 0 :(得分:25)
答案 1 :(得分:8)
我使用一组面积图来模拟可变宽度列/条形图。比如说,每个栏/栏都由一个矩形区域表示。
请参阅我的小提琴演示(http://jsfiddle.net/calfzhou/TUt2U/)。
$(function () {
var rawData = [
{ name: 'A', x: 5.2, y: 5.6 },
{ name: 'B', x: 3.9, y: 10.1 },
{ name: 'C', x: 11.5, y: 1.2 },
{ name: 'D', x: 2.4, y: 17.8 },
{ name: 'E', x: 8.1, y: 8.4 }
];
function makeSeries(listOfData) {
var sumX = 0.0;
for (var i = 0; i < listOfData.length; i++) {
sumX += listOfData[i].x;
}
var gap = sumX / rawData.length * 0.2;
var allSeries = []
var x = 0.0;
for (var i = 0; i < listOfData.length; i++) {
var data = listOfData[i];
allSeries[i] = {
name: data.name,
data: [
[x, 0], [x, data.y],
{
x: x + data.x / 2.0,
y: data.y,
dataLabels: { enabled: true, format: data.x + ' x {y}' }
},
[x + data.x, data.y], [x + data.x, 0]
],
w: data.x,
h: data.y
};
x += data.x + gap;
}
return allSeries;
}
$('#container').highcharts({
chart: { type: 'area' },
xAxis: {
tickLength: 0,
labels: { enabled: false}
},
yAxis: {
title: { enabled: false}
},
plotOptions: {
area: {
marker: {
enabled: false,
states: {
hover: { enabled: false }
}
}
}
},
tooltip: {
followPointer: true,
useHTML: true,
headerFormat: '<span style="color: {series.color}">{series.name}</span>: ',
pointFormat: '<span>{series.options.w} x {series.options.h}</span>'
},
series: makeSeries(rawData)
});
});
答案 2 :(得分:1)
如果你拥有获得更优的Marimekko图表的许可证,那么Fusioncharts可能是最好的选择......
我已经做了一些尝试在高图中获得Marimekko图表解决方案的工作。它并不完美,但近似于Fusion Charts页面上的第一个Marimekko图表示例......
http://www.fusioncharts.com/resources/chart-tutorials/understanding-the-marimekko-chart/
关键是使用dateTime轴,因为该模式为您在X轴上分布点和线的方式提供了更大的灵活性,这使您能够在此轴上构建可变大小的“条形” 。我使用0-1000秒的空间,在图表外部计算出这个比例的映射,以近似百分比值来调整垂直线。这里(http://jsfiddle.net/miken/598d9/2/)是一个创建可变宽度柱形图的jsfiddle示例。
$(function () {
var chart;
Highcharts.setOptions({
colors: [ '#75FFFF', '#55CCDD', '#60DD60' ]
});
$(document).ready(function() {
var CATEGORY = { // number out of 1000
0: '',
475: 'Desktops',
763: 'Laptops',
1000: 'Tablets'
};
var BucketSize = {
0: 475,
475: 475,
763: 288,
1000: 237
};
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'area'
},
title: {
text: 'Contribution to Overall Sales by Brand & Category (in US$)<br>(2011-12)'
},
xAxis: {
min: 0,
max: 1000,
title: {
text: '<b>CATEGORY</b>'
},
tickInterval: 1,
minTickInterval: 1,
dateTimeLabelFormats: {
month: '%b'
},
labels: {
rotation: -60,
align: 'right',
formatter: function() {
if (CATEGORY[this.value] !== undefined) {
return '<b>' + CATEGORY[this.value] + ' (' +
this.value/10 + '%)</b>';
}
}
}
},
yAxis: {
max: 100,
gridLineWidth: 0,
title: {
text: '<b>% Share</b>'
},
labels: {
formatter: function() {
return this.value +'%'
}
}
},
tooltip: {
shared: true,
useHTML: true,
formatter: function () {
var result = 'CATEGORY: <b>' +
CATEGORY[this.x] + ' (' + Highcharts.numberFormat(BucketSize[this.x]/10,1) + '% sized bucket)</b><br>';
$.each(this.points, function(i, datum) {
if (datum.point.y !== 0) {
result += '<span style="color:' +
datum.series.color + '"><b>' +
datum.series.name + '</b></span>: ' +
'<b>$' + datum.point.y + 'K</b> (' +
Highcharts.numberFormat(
datum.point.percentage,2) +
'%)<br/>';
}
});
return (result);
}
},
plotOptions: {
area: {
stacking: 'percent',
lineColor: 'black',
lineWidth: 1,
marker: {
enabled: false
},
step: true
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: 0,
y: 100,
borderWidth: 1,
title: {
text : 'Brand:'
}
},
series: [ {
name: 'HP',
data: [
[0,298],
[475,109],
[763,153],
[1000,153]
]
}, {
name: 'Dell',
data: [
[0,245],
[475,198],
[763,120],
[1000,120]
]
}, {
name: 'Sony',
data: [
[0,335],
[475,225],
[763,164],
[1000,164]
]
}]
},
function(chart){
// Render bottom line.
chart.renderer.path(['M', chart.plotLeft, chart.plotHeight + 66, 'L', chart.plotLeft+chart.plotWidth, chart.plotHeight + 66])
.attr({
'stroke-width': 3,
stroke: 'black',
zIndex:50
})
.add();
for (var category_idx in CATEGORY) {
chart.renderer.path(['M', (Math.round((category_idx / 1000) * chart.plotWidth)) + chart.plotLeft, 66, 'V', chart.plotTop + chart.plotHeight])
.attr({
'stroke-width': 1,
stroke: 'black',
zIndex:4
})
.add();
}
});
});
});
它添加了一个额外的数组,允许您将类别名称映射到第二个tic值,以便为您提供您可能需要的更多“类别”视图。我还在底部添加了代码,在不同的列和图表的底线之间添加垂直分隔线。它可能需要对周围标签的大小进行一些调整等,我在这里作为数学的一部分用像素硬编码,但它应该是可行的。
使用'百分比'类型重音可让您使用y比例计算原始数据中的百分比总和,而如上所述,您需要对x轴进行自己的数学运算。我更依赖于工具提示功能来提供标签等,而不是图表本身的标签。
这项工作的另一个重大改进是找到一种方法,使工具提示悬停区域和标签聚焦并居中并包含条形本身,而不是现在每个条形的右边框。如果有人想添加,请随意到这里。
答案 3 :(得分:0)
如果我做对了,您希望每个条形都具有不同的宽度。我遇到了同样的问题,为找到提供此选项的库付出了很多努力。我得出了结论-没有。
无论如何,我都玩了一些高级图表,变得很有创意,并提出了以下建议:
您提到您希望数据看起来像这样:data: [[5, 3.4], [3, 6], [4, 3.4]]
,第一个值是高度,第二个值是宽度。
让我们使用highcharts的柱状图来完成它。
第1步:
为了更好地区分条形图,请将每个条形图输入为新系列。由于我是动态生成数据的,因此必须动态分配新系列:
const objects: any = [];
const extra = this.data.length - 1;
this.data.map((range) => {
const obj = {
type: 'column',
showInLegend: false,
data: [range[1]],
animation: true,
borderColor: 'black',
borderWidth: 1,
color: 'blue'
};
for (let i = 0; i < extra; i++) {
obj.data.push(null);
}
objects.push(obj);
});
this.chartOptions.series = objects;
这样,您的不同系列将如下所示:
series: [{
type: 'column',
data: [5, 3.4]
}, {
type: 'column',
data: [3, 6]
}, {
type: 'column',
data: [4, 3.4]
}]
第2步:
将其分配为高图的绘图选项:
plotOptions: {
column: {
pointPadding: 0,
borderWidth: 0,
groupPadding: 0,
shadow: false
}
}
第3步:
现在,让我们发挥创造力-为所有条形设定相同的起点,我们需要将每个条形图移至图形的起点:
setColumnsToZero() {
this.data.map((item, index) => {
document.querySelector('.highcharts-series-' + index).children[0].setAttribute('x', '0');
});
}
第4步:
getDistribution() {
let total = 0;
// Array including all of the bar's data: [[5, 3.4], [3, 6], [4, 3.4]]
this.data.map(item => {
total = total + item[0];
});
// MARK: Get xAxis' total width
const totalWidth = document.querySelector('.highcharts-axis-line').getBoundingClientRect().width;
let pos = 0;
this.data.map((item, index) => {
const start = item[0];
const width = (start * totalWidth) / total;
document.querySelector('.highcharts-series-' + index).children[0].setAttribute('width', width.toString());
document.querySelector('.highcharts-series-' + index).children[0].setAttribute('x', pos.toString());
pos = pos + width;
this.getPointsPosition(index, totalWidth, total);
});
}
第4步:
让我们到达xAxis的要点。在第一个功能中,修改已经存在的点,将最后一个点移到轴的末端,然后隐藏其他点。在第二个函数中,我们克隆最后一个点,将其修改为总共6个或3个xAxis点,然后将每个点移动到正确的位置
getPointsPosition(index, totalWidth, total) {
const col = document.querySelector('.highcharts-series-' + index).children[0];
const point = (document.querySelector('.highcharts-xaxis-labels').children[index] as HTMLElement);
const difference = col.getBoundingClientRect().right - point.getBoundingClientRect().right;
const half = point.getBoundingClientRect().width / 2;
if (index === this.data.length - 1) {
this.cloneNode(point, difference, totalWidth, total);
} else {
point.style.display = 'none';
}
point.style.transform = 'translateX(' + (+difference + +half) + 'px)';
point.innerHTML = total.toString();
}
cloneNode(ref: HTMLElement, difference, totalWidth, total) {
const width = document.documentElement.getBoundingClientRect().width;
const q = total / (width > 1000 && ? 6 : 3);
const w = totalWidth / (width > 1000 ? 6 : 3);
let val = total;
let valW = 0;
for (let i = 0; i < (width > 1000 ? 6 : 3); i++) {
val = val - q;
valW = valW + w;
const clone = (ref.cloneNode(true) as HTMLElement);
document.querySelector('.highcharts-xaxis-labels').appendChild(clone);
const half = clone.getBoundingClientRect().width / 2;
clone.style.transform = 'translateX(' + (-valW + difference + half) + 'px)';
const inner = Math.round(val * 100) / 100;
clone.innerHTML = inner.toString();
}
}
最后,我们有一个看起来像这样的图(不是这个给定示例中的数据,而是对于[[20, 0.005], [30, 0.013333333333333334], [20, 0.01], [30, 0.005555555555555555], [20, 0.006666666666666666]]
来说,第一个值是宽度,第二个值是高度):
可能需要做一些修改才能100%适合您的情况。 F.e.我必须将xAxis的点调整为特定的起点和终点-我省去了这部分。