Reputation: 15688
I'm trying to create a highchart that resembles the following but am not sure how to configure my parameters and rather confused about the data structure
Notes: Each column should be independent. They do not share any data/series amongst each other. Data within a column should be contained within its own column.
Essentially, I want to have five different series on the y-axis, where each series will stack its data and not pass that data into the other axises.
ie: Asset Class has data for Stocks, ETFS, Cash and that data should only be in the Asset Class column. Similarly, Industry will have data for Sector Level and etc.
Currently, my output resembles the standard stacked-bar-chart layout
Here is my current data structure, which I am sure will need a big revision:
categories: ["", "Utilities", "Energy", "Funds", "Financial", "Consumer, Cyclical", "Consumer, Non-cyclical", "Communications", "Basic Materials", "Industrial", "Technology", "Other", "Government"]
series: [
{name: "Cash", data: Array(13)},
{name: "Equity", data: Array(13)},
{name: "Fixed Income", data: Array(13)},
{name: "Fund", data: Array(13)}
]
My chart code if needed:
this.options = {
chart: {
type: 'column',
height: 500,
style: {
fontFamily: "Arial"
}
},
title: {
text: ""
},
xAxis: {
categories: categories,
labels: {
style: {
fontSize: "14px"
}
}
},
yAxis: {
min: 0,
title: {
text: ""
},
labels: {
formatter: function () {
let valueString = (
this.value > 999.99 && this.value <= 999999.99 ?
"$" + (this.value / 1000).toFixed(0) + "K" : this.value > 999999.99 ?
"$" + (this.value / 1000000).toFixed(1) + "M" : this.value
)
return valueString
},
style: {
fontSize: "14px",
}
}
},
legend: {
align: 'right',
verticalAlign: 'top',
layout: "vertical",
x: 0,
y: 50,
itemStyle: {
fontSize: "16px",
color: "#6c6c6c",
},
symbolPadding: 8,
itemMarginTop: 10,
shadow: false,
labelFormatter: function () {
return `${this.name}`
}
},
tooltip: {
formatter: function () {
let name = this.series.name
let value = this.y
let valueString = `$${value.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`
let total = this.point.stackTotal
let percentage = ((value / total) * 100).toFixed(2)
let percentageString = `(${percentage})%`
return `<b>${name}</b> <br> ${valueString} ${percentageString}`
},
style: {
fontSize: "14px",
},
backgroundColor: "#ffffff"
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false
}
},
series: {
borderColor: "rgba(0, 0, 0, 0)"
}
},
series: series
}
We also discussed whether it would be possible to have a list of categories, and only use a portion of those categories depending on the column we have selected. Any help will be greatly appreciated :)
Upvotes: 2
Views: 735
Reputation: 39069
Relative to the description, your series structure should look this way:
series = [{
name: "Cash",
data: [
{x: 0, y: 5},
{x: 0, y: 2},
{x: 0, y: 4}
]
}, {
name: "Equity",
data: [
{x: 1, y: 4},
{x: 1, y: 3},
{x: 1, y: 4}
]
}, {
name: "Fixed Income",
data: [
{x: 2, y: 4},
{x: 2, y: 5},
{x: 2, y: 2}
]
}]
To make the hover series look 'active', you can use update
method for the series points in mouseOver
and mouseOut
events:
var categories = ["Utilities", "Energy", "Funds"],
colors = ['red', 'green', 'blue'],
series = [...],
i = 0,
newCategories,
chartCategories = [];
for (; i < series.length; i++) {
chartCategories.push('');
}
Highcharts.chart('container', {
...,
plotOptions: {
column: {
...,
events: {
mouseOver: function() {
this.points.forEach(function(p, i) {
p.update({
color: colors[i]
});
}, this);
newCategories = chartCategories.slice();
newCategories.splice(
this.index, 1, categories[this.index]
);
this.xAxis.setCategories(
newCategories
);
},
mouseOut: function() {
this.points.forEach(function(p) {
p.update({
color: ''
});
}, this);
this.xAxis.setCategories(
chartCategories
);
}
}
}
}
});
Live demo: http://jsfiddle.net/BlackLabel/Ljfqe0ts/
API Reference: https://api.highcharts.com/highcharts/series.column.events
Upvotes: 3