I've been working on a visualisation using Sankey chart using Highcharts library. It looks like below.
I need help with adding labels to each column as highlighted in the above image. I couldn't find any workaround using formatters since there are no x & y axes available in sankey.
It would be great someone here helps me with doing it.
you can find my jsfiddle here.
EDIT: I was able to plot the x & y axes now, but trying to place the labels exactly below each column. Broken fiddle link updated.
const data = [{
"from": "step1_x",
"to": "step2_x",
"weight": 100
},
{
"from": "step1_x",
"to": "step2_y",
weight: 35
},
{
"from": "step1_x",
"to": "step2_z",
weight: 50
},
{
"from": "step1_y",
"to": "step2_y",
weight: 55
},
{
"from": "step1_y",
"to": "step2_x",
weight: 20
},
{
"from": "step1_y",
"to": "step2_z",
weight: 30
},
{
"from": "step1_z",
"to": "step2_y",
weight: 18
},
{
"from": "step1_z",
"to": "step2_x",
weight: 15
},
{
"from": "step1_z",
"to": "step2_z",
weight: 40
},
{
"from": "step2_x",
"to": "step3_x",
"weight": 50
},
{
"from": "step2_x",
"to": "step3_y",
weight: 55
},
{
"from": "step2_x",
"to": "step3_z",
weight: 30
},
{
"from": "step2_y",
"to": "step3_y",
weight: 90
},
{
"from": "step2_y",
"to": "step3_x",
weight: 40
},
{
"from": "step2_y",
"to": "step3_z",
weight: 51
},
{
"from": "step2_z",
"to": "step3_y",
weight: 30
},
{
"from": "step2_z",
"to": "step3_x",
weight: 40
},
{
"from": "step2_z",
"to": "step3_z",
weight: 90
},
];
const nodes = [{
"id": "step1_x",
"name": "X",
color: 'black'
}, {
"id": "step2_x",
"name": "X",
color: 'black',
},
{
"id": "step3_x",
"name": "X",
color: 'black',
},
{
"id": "step1_y",
"name": "Y",
color: '#f15c80'
}, {
"id": "step2_y",
"name": "Y",
color: '#f15c80'
}, {
"id": "step3_y",
"name": "Y",
color: '#f15c80'
}, {
"id": "step1_z",
"name": "Z",
color: '#f7a35c'
}, {
"id": "step2_z",
"name": "Z",
color: '#f7a35c'
}, {
"id": "step3_z",
"name": "Z",
color: '#f7a35c'
},
];
Highcharts.chart('container', {
title: {
text: 'Highcharts Sankey Diagram'
},
yAxis: {
labels: {
enabled: true,
formatter:function () {
return '1231';
}
}
},
series: [{
data: data,
nodes: nodes,
type: 'sankey',
name: 'Sankey demo series',
nodeWidth: 20
}],
plotOptions: {
sankey: {
dataLabels: {
overflow: 'allow',
crop: true,
enabled: true,
formatter: function () {
return this.point.weight;
}
}
}
}
});
You can add the labels by using renderer.text method. Example below:
const labels = ['column 1', 'column 2', 'column 3'];
Highcharts.chart('container', {
chart: {
spacingBottom: 50,
events: {
render: function() {
const positions = [30, this.chartWidth / 2, this.chartWidth - 30];
if (this.customLabels) {
this.customLabels.forEach((customLabel, i) => {
customLabel.attr({
x: positions[i],
y: this.chartHeight - 20
});
});
} else {
this.customLabels = [];
labels.forEach((label, i) => {
this.customLabels.push(
this.renderer.text(labels[i])
.attr({
x: positions[i],
y: this.chartHeight - 20,
align: 'center'
})
.css({
fontSize: '12px'
})
.add()
);
});
}
}
}
},
...
});
Live demo: https://jsfiddle.net/BlackLabel/tq79c21e/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
Related
I'm using Highchart to create a donut chart with a rounded corner. Unfortunately, the chart is not fully circular.
var data2 = [
{
"data": [
{
"name": "Positve",
"y": 50,
"color": "#2CA02C",
"sliced": true
},
{
"name": "Negative",
"y": 25,
"color": "#B23333",
"sliced": true
},
{
"name": "Neutral",
"y": 25,
"color": "#E5CF73",
"sliced": true
}
]
}
]
window.mychart = Highcharts.chart('container', {
chart: {
type: 'pie',
plotShadow: false,
},
credits: {
enabled: false
},
plotOptions: {
pie: {
innerSize: '100%',
borderWidth: 10,
borderColor: null,
slicedOffset: 6,
dataLabels: {
connectorWidth: 0,
enabled: false
}
}
},
title: {
verticalAlign: 'middle',
floating: true,
text: ''
},
legend: {
},
series: data2,
});
Here is the jsfiddle link to it:
JsFiddle
Only one point can be sliced, so use data without the sliced property or set slicedOffset to 0.
"data": [{
"name": "Positve",
"y": 50,
"color": "#2CA02C"
},
{
"name": "Negative",
"y": 25,
"color": "#B23333"
},
{
"name": "Neutral",
"y": 25,
"color": "#E5CF73"
}
]
Live demo: http://jsfiddle.net/BlackLabel/1usgc4a6/
API Reference:
https://api.highcharts.com/highcharts/series.pie.data.sliced
https://api.highcharts.com/highcharts/series.pie.slicedOffset
Plot bands in highchart export server is not working properly. I want the output same as shown in jsfiddle below.
I want the color plot band to show on y axis with width 20.
This is expected output: https://jsfiddle.net/vc6r8y3n/
Attached image is actual output when we use high-chart export server.
but when I tried same JavaScript json object on
http://export.highcharts.com/
its giving me image with plot band color spread on whole chart. its not considering width for 'y' or 'x' axis in export server. I gave attached image of export chart.
Why highchart behaving differently in both the cases.
Highchart JSON is same as in JSfiddle.
Actual image.
Expected is what it display in Jsfiddle. https://jsfiddle.net/vc6r8y3n/
{
"chart": {
"height": 350,
"width": 600,
"style": {
"fontFamily": "\"Arial\", sans-serif",
"fontSize": "16px"
},
"backgroundColor": "transparent"
},
"title": {
"text": null
},
"credits": {
"enabled": false
},
"legend": {
"align": "center",
"layout": "horizontal",
"verticalAlign": "bottom",
"symbolHeight": 5,
"symbolWidth": 5,
"symbolRadius": 0,
"itemDistance": 10,
"itemStyle": {
"fontSize": "5px",
"fontWeight": "bold",
"fontFamily": "\"Arial\", sans-serif"
},
"borderWidth": 0,
"padding": 0,
"margin": 5
},
"xAxis": {
"categories": [
"Sep-2020",
"Oct-2020",
"Nov-2020",
"Dec-2020",
"Jan-2021",
"Feb-2021"
],
"labels": {
"style": {
"fontSize": "4px",
"fontFamily": "\"Arial\", sans-serif",
"color": "#000"
},
"y": 5
},
"gridLineColor": "transparent",
"gridLineWidth": 0,
"minorGridLineWidth": 0,
"lineColor": "#9A9A9A",
"zIndex": 9999999
},
"yAxis": [
{
"title": {
"text": ""
},
"min": 0,
"max": 100,
"tickInterval": 20,
"plotBands": [
{
"color": "rgb(204,0,0)",
"from": 0,
"to": 30.99,
"zIndex": 3
},
{
"color": "rgb(226,113,113)",
"from": 31,
"to": 44.99,
"zIndex": 3
},
{
"color": "rgb(247,209,34)",
"from": 45,
"to": 54.99,
"zIndex": 3
},
{
"color": "rgb(136,207,136)",
"from": 55,
"to": 68.99,
"zIndex": 3
},
{
"color": "rgb(68,180,68)",
"from": 69,
"to": 87.99,
"zIndex": 3
},
{
"color": "rgb(0,153,0)",
"from": 88,
"to": 100,
"zIndex": 3
}
],
"width": 20
}
],
"plotOptions": {
"column": {
"dataLabels": {
"enabled": true
}
}
},
"series": [
{
"name": "Line1",
"type": "column",
"data": [
{
"y": 61,
"color": "#5b9bd5"
},
{
"y": 41,
"color": "#5b9bd5"
},
{
"y": 21,
"color": "#5b9bd5"
},
{
"y": 81,
"color": "#5b9bd5"
},
{
"y": 31,
"color": "#5b9bd5"
},
{
"y": 71,
"color": "#5b9bd5"
}
],
"color": "#5b9bd5",
"showInLegend": true
},
{
"name": "Line 2",
"type": "column",
"data": [
null,
null,
null,
null,
null,
1
],
"color": "#00B050"
},
{
"name": "Line 3",
"type": "spline",
"data": [
null,
{
"y": 45
},
{
"y": 38
},
{
"y": 32
},
{
"y": 40
},
{
"y": 48
}
],
"color": "#9A0229"
}
]
}
enter image description here
I need to be able to apply background coloring (and text coloring to maintain contrast) to category labels.
I couldn't find an easy way to set each category label independently and came up with a working solution but now the width of my label column is too wide and applying marginLeft doesn't work.
First is there an easier way to achieve what I want or a solution to the width.
Here's the result:
and fiddle can be found here
Highcharts.ganttChart('container', {
chart: {
// marginLeft: 400,
events: {
load: function() {
for (var tickPos in this.yAxis[0].ticks) {
console.log(tickPos);
var ch = this.yAxis[0].chart;
var tick = this.yAxis[0].ticks[tickPos];
var label = tick.label;
if (typeof label !== "undefined") {
var text = label.textStr;
var obj = JSON.parse(text);
var element = label.element;
element.textContent = obj.name;
if (typeof obj.background !== "undefined") {
element.style["background-color"] = obj.background;
}
if (typeof obj.color !== "undefined") {
element.style["color"] = obj.color;
}
}
}
}
}
},
title: {
text: 'Highcharts Gantt Chart'
},
subtitle: {
text: 'With linked to split'
},
xAxis: {
minPadding: 0.05,
maxPadding: 0.05
},
"yAxis": [{
"scrollbar": {
"enabled": true
},
labels: {
useHTML: true
},
"uniqueNames": true
}],
tooltip: {
outside: true
},
rangeSelector: {
enabled: true,
selected: 5
},
time: {
useUTC: true
},
plotOptions: {
column: {
grouping: true
}
},
"series": [{
"name": "main",
"tooltip": {
"headerFormat": null
},
"data": [{
"name": '{"name": "Color prep and printing", "background":"green", "color":"white"}',
"id": "_dqbcsMWXEeeTdKTuQU2hRA",
"start": 1577836800000,
"end": 1582934400000,
"color": {
"patternIndex": 0
}
}, {
"name": '{"name": "Send to color house", "background":"blue", "color":"white"}',
"id": "_dqkmv8WXEeeTdKTuQU2hRA",
"parent": "_dqbcsMWXEeeTdKTuQU2hRA",
"start": 1577836800000,
"end": 1580428800000,
"duration": 30
}, {
"name": '{"name": "Generate proofs", "background":"teal", "color":"white"}',
"id": "_dq3hkMWXEeeTdKTuQU2hRA",
"parent": "_dqbcsMWXEeeTdKTuQU2hRA",
"start": 1578614400000,
"end": 1579651200000,
"duration": 12,
"dependency": [{
"to": "_dqkmv8WXEeeTdKTuQU2hRA"
}]
}, {
"name": '{"name": "Print and ship", "background":"crimson"}',
"id": "_drLDlcWXEeeTdKTuQU2hRA",
"parent": "_dqbcsMWXEeeTdKTuQU2hRA",
"start": 1581292800000,
"end": 1582934400000,
"duration": 19,
"dependency": [{
"to": "_dq3hkMWXEeeTdKTuQU2hRA"
}]
}],
"dataLabels": [{}, {
"enabled": true,
"align": "right",
"format": "{point.duration}"
}]
}],
});
To increase the width, you can set width style:
yAxis: {
labels: {
useHTML: true,
style: {
width: '300px',
textOverflow: 'ellipsis'
}
},
...
},
Live demo: https://jsfiddle.net/BlackLabel/nkz9xmh0/
API Reference: https://api.highcharts.com/gantt/yAxis.labels.style
is it possible in highchart to add the legend in each column with keeping
the value or label of each coulmn on top of the column like the attached image and this is my code on jsfiddle enter link description here
$('#container').highcharts({
"chart": {
"type": "column",
"style": {
"fontFamily": "Arial",
"fontSize": 12
},
"backgroundColor": "transparent",
"width": 460
},
"plotOptions": {
"series": {
"dataLabels": {
"enabled": true,
"format": "${y}"
},
"pointPadding": 0,
"groupPadding": 0.1
}
},
"xAxis": [{
"categories": [
"Jan",
"Feb",
"Mar"],
}],
"series": [{
"name": "2014",
"color": "#231E1E",
"marker": {
"radius": 3
},
"showInLegend": true,
"connectNulls": true,
"tooltip": [
],
"data": [
10,
20,
30]
}, {
"name": "2015",
"color": "#1DBEDE",
"marker": {
"radius": 3
},
"showInLegend": true,
"connectNulls": true,
"tooltip": [
],
"data": [
12,
22,
32]
}]
});
You can use the plotOptions.series.dataLabels.formatter instead of format:
dataLabels: {
enabled: true,
useHTML: true,
y: 30,
formatter: function() {
return "$" + this.y + "<br><br><br>" +
"<div style='-webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); -o-transform: rotate(90deg);'>" +
this.series.name + "</div>";
}
}
You can tell the chart exactly the way you want the labels to be shown. this.y is the dollar values and this.series.name is the name of the series which are 2014 and 2015. y: 30 is where the label should be placed in respect to the top of the column. Here's a DEMO.
PS: The problem is that you cannot have two datalabels for each column. You either have to set the location for the top label (as mentioned in my answer) or set it for the bottom labels in this example. As you can see there are some problems in each example, but you can't have both. However there could be a workaround like this, but its not clean.
You can try to use stackLabels. Of course that solution will work only when you don't use stacking at all. See demo: http://jsfiddle.net/LLExL/4855/
Code:
yAxis: {
stackLabels: {
enabled: true,
formatter: function() {
return "$" + this.total;
}
}
},
"plotOptions": {
"series": {
stacking: "normal",
"dataLabels": {
"enabled": true,
rotation: -90,
"format": "{point.series.name}"
},
"pointPadding": 0,
"groupPadding": 0.1
}
},
Regarding aligning labels to the bottom, see this question.
I made some changes on solution of #Raeen to be exactly what i want
and here is the example demo
enter code jQuery('#container').highcharts({
"chart": {
"type": "column",
"style": {
"fontFamily": "Arial",
"fontSize": 12
},
"backgroundColor": "transparent",
"width": 460
},
title:{
text:''
},
tooltip: {
enabled: false
},
"plotOptions": {
"series": {
"dataLabels": {
"inside":true,
"enabled": true,
useHTML: true,
y: 30,
formatter: function() {
var html ='';
labelHeight = this.point.shapeArgs.height-15;
html += '<div class="data-label-wrapper" style="height:'+labelHeight+'px;">';
html += '<span style="color:'+this.series.color+';">$'+this.y+'</span>';
html += '<span class="serie-name" style="top:'+(labelHeight-25)+'px">'+this.series.name+'</span>';
html += '</div>';
return html ;
}
},
"pointPadding": 0,
"groupPadding": 0.1
}
},
"xAxis": [{
"categories": [
"Jan",
"Feb",
"Mar"],
}],
"series": [{
"name": "2014",
"color": "#231E1E",
"marker": {
"radius": 3
},
"showInLegend": false,
"connectNulls": true,
"tooltip": [
],
"data": [
10,
20,
30]
}, {
"name": "2015",
"color": "#1DBEDE",
"marker": {
"radius": 3
},
"showInLegend": false,
"connectNulls": true,
"tooltip": [
],
"data": [
12,
22,
32]
}] });
and now what i need if its possible to controll the number of gridlines numbers
to be like 3 instead of 8 that would be perfect.
Can someone tell me why this chart is rendering properly in drill up? The code is wrapping arc3d. I have provided the code and also the JFiddle for reference. When you click on the graph it drills down perfectly but while drilling up the graph is not rendering properly. it holds the color of the drilled slice.
(http://jsfiddle.net/subhasispatra/np0bn3ps/)
$(function () {
Highcharts.setOptions({
lang: {
drillUpText: '<Back'
}
});
Highcharts.wrap(Highcharts.SVGRenderer.prototype, 'arc3d', function (proceed) {
var result = proceed.apply(this, [].slice.call(arguments, 1));
result.fadeIn = result.show;
return result;
});
$('#container').highcharts({
"plotOptions": {
"pie": {
"point": {
"events": {
"click": function () {
if (this.options != undefined && this.options != null && this.options.url != null && this.options.url.length > 0) location.href = this.options.url;
else return;
}
}
},
"dataLabels": {
"enabled": true,
"style": {
"fontWeight": "bold",
"fontFamily": "Arial",
"fontSize": "10"
},
"color": "#000000"
},
"shadow": true,
"curson": "pointer",
"depth": 30,
"allowPointSelection": true,
"showInLegend": true
}
},
"drilldown": {
"series": [{
"id": "Draft",
"data": [{
"name": "15-21 DAYS",
"url": "http://www.google.com",
"y": 1
}, {
"name": "22-30 DAYS",
"url": "http://www.google.com",
"y": 1
}]
}, {
"id": "Canceled",
"data": [{
"name": "15-21 DAYS",
"url": "http://www.google.com",
"y": 0
}, {
"name": "22-30 DAYS",
"url": "http://www.google.com",
"y": 1
}]
}],
"drillUpButton": {
"relativeTo": "spacingBox",
"theme": {
"style": {
"fontSize": "7pt"
}
},
"y": 0,
"x": 0
}
},
"series": [{
"name": "SERIES",
"data": [{
"drilldown": "Draft",
"name": "Draft",
"y": 2
}, {
"drilldown": "Canceled",
"name": "Canceled",
"y": 1
}]
}],
"yAxis": {
"title": {
"style": {
"color": "#000000",
"fontSize": "10"
}
},
"labels": {
"style": {
"fontWeight": "normal",
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "10"
}
}
},
"title": {
"text": "Orders created in last 30 days"
},
"legend": {
"itemStyle": {
"fontWeight": "normal",
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "10"
},
"layout": "vertical",
"align": "left",
"verticalAlign": "middle"
},
"chart": {
"renderTo": "container",
"options3d": {
"enabled": "true",
"alpha": 40,
"beta": 0,
"depth": 40
},
"backgroundColor": "rgba(255, 255, 255, 0.1)",
"type": "pie"
},
"credits": {
"enabled": false
},
"xAxis": {
"title": {
"style": {
"color": "#000000",
"fontSize": "10"
}
},
"labels": {
"style": {
"fontWeight": "normal",
"color": "#000000",
"fontFamily": "Arial",
"fontSize": "10"
}
}
}
});
});
The problem is due to 3D rendering. Disable 3D options and it'll work fine.