Drilldown in Sankey Diagram - highcharts

I'm looking for example code on how to implement a drilldown in a sankey diagram.
I tried using the drilldown code from the column drilldown demo but it didn't work for sankey.
The intended functionality is very similar to a dendogram, i.e- click a node to hide reveal child nodes.
Example:
https://jsfiddle.net/y_tddel/d7jby2z1/5/
.
In this example each node in the second column will be clickable and have their own child nodes.The expanded view of Indo-Iranian node is shown as as an example.

Series.point.events can be used to trigger the event when the user clicks on any node, and update the series data, and adding a back button.
Link: https://api.highcharts.com/highcharts/series.sankey.point.events.click
Look at the following code sample:
Highcharts.chart('container', {
series: [{
point: {
events: {
click: function (e) {
console.log(e, 'e')
let series = this.series,
chart = series.chart;
if (this.isNode) {
if (isDrilldown[isDrilldown.length - 1] != this.name && drilldown_data.hasOwnProperty(this.name)) {
chart.backButton = chart.renderer.button('back', chart.plotLeft, 20, function () {
isDrilldown.pop();
d = JSON.parse(JSON.stringify(drilldown_data[isDrilldown[isDrilldown.length - 1]]));
series.update({data: d});
chart.backButton.destroy();
chart.title.show();
}).add()
isDrilldown.push(this.name);
chart.title.hide()
this.series.update({
data: JSON.parse(JSON.stringify(drilldown_data[this.name]))
})
}
}
}
}
},
keys: ['from', 'to', 'weight', 'drilldown'],
data: JSON.parse(JSON.stringify(plot_data)),
type: 'sankey'
}],
});
Demo: https://jsfiddle.net/deveshgoyal/1zcnuq5b/2/

Current drilldown module is not compatible with the sankey series. You will need to create your own drilldown logic. Below is a basic demo which shows how to update series on click event - which could be treated as an drilldown to other series.
Demo: https://jsfiddle.net/BlackLabel/hn19xga5/
events: {
click() {
let series = this.series,
chart = series.chart;
if (!isDrilldown) {
chart.backButton = chart.renderer.button('back', 20, 20, function() {
series.update({
data: initialData
})
chart.backButton.destroy();
isDrilldown = false;
}).add()
isDrilldown = true;
}
this.series.update({
data: drilldown1
})
}
}
API: https://api.highcharts.com/highcharts/series.sankey.data.events.click
API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#button
API: https://api.highcharts.com/class-reference/Highcharts.Series#update

Related

Add dataLabels to solid guage

How can i add data label in front of each point in solid gauge chart. I am try to achieve something like this
Thanks
You can add custom data labels in render event, for example:
chart: {
...,
events: {
render: function() {
var dataLabels = ['Custom DL1', 'Custom DL2', 'Custom DL3'],
chart = this,
series = chart.series;
dataLabels.forEach(function(dl, i) {
if (!series[i].customDL) {
series[i].customDL = chart.renderer.text(dl)
.attr({
zIndex: 10
})
.add(series[i].group);
}
series[i].customDL.translate(
chart.chartWidth / 2 + 10,
chart.plotHeight / 2 - series[i].points[0].shapeArgs.innerR -
(series[i].points[0].shapeArgs.r - series[i].points[0].shapeArgs.innerR) / 2
);
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/c5eq2htg/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text

HighCharts. Is it possible to access Highcharts classes through a label context?

Task:
I need to programmatically calculate the position of the labels relative to the labels of the chart.
Problem:
Dependence HighCharts is loaded lazily. I do not have direct access to the dependency, respectively, no access to the classes. How else can I create an object from the tick class? Is it possible to create an object through a context in the label formatting function?
Highcharts.chart('container', {
chart: {
events: {
render() {
var ticks = this.xAxis[0].ticks,
ticksPositions = this.xAxis[0].tickPositions,
tick0x,
tick1x;
var getPosition = function (tick) {
var axis = tick.axis;
return Highcharts.Tick.prototype.getPosition.call(tick, axis.horiz, tick.pos, axis.tickmarkOffset);
};
tick0x = getPosition(ticks[ticksPositions[0]]).x;
tick1x = getPosition(ticks[ticksPositions[2]]).x;
this.xAxis[0].labelGroup.translate((tick1x - tick0x)/2)
}
}
},
series: [{
data: [29.9, 71.5, 106.4]
}]
});

How can I use data.table or data.csv and extra data for click event handling

I have a pie chart built using a data.table (HTML table). http://jsfiddle.net/m78Lwkqt/2/
I want to use a 3rd column of the table to drive a click to a particular URL.
series:[
{
type: 'pie',
animation: false,
point:{
events:{
click:
function (event)
{
// I want to get the 3rd column of the table's value
// that corresponds to this point.
alert(this.y);
}
}
}
}
]
Found an answer: http://jsfiddle.net/ryanreid22/m78Lwkqt/4/
The trick is to add a seriesMapping value (in this case I've called it 'accountCode') that can be used in the point.click handler.
data: {
table: 'smry_t_pb_outlay_by_account',
seriesMapping: [{
x: 0, // X values are pulled from column 0 by default
y: 1, // Y values are pulled from column 1 by default
accountCode: 2 // used in the point.click below
}]
},
events: {
click:
function (event) {
alert(this.accountCode);
}
}
You could use a jQuery selector to get all the tds from the third column, and when needed match this.x from this click event up against the array you got from the jQuery selector.
For example, getting the third column using a jQuery selector:
var thirdColumn = $("#smry_t_pb_outlay_by_account tr td:nth-child(3)");
And then using this array inside your point.events.click to get the data:
point: {
events: {
click: function (event) {
alert(thirdColumn[this.x].innerHTML);
}
}
}
See this JSFiddle demonstration of the code.

Remove data labels when ploting and exporting graphs

So, I have stacked bar chart and I want to hide data labels when they don't fit in the area. for Example in Category 8, not to have data label "4" at all.
This is a similar question bolow:
Highcharts stacked bar chart hide data labels not to overlap
But My problem is I also need to hide lables on exporting
I have done this code after generating graph to hide labales
$.each(this.chartObject.series,function(i,data_series){
if (data_series.visible){
$.each(data_series.data,function(j,data){
if(data.yBottom != null && data.plotY != null){
if(data.yBottom - data.plotY < 15){
if (typeof data.dataLabel != 'undefined'){
data.dataLabel.hide();
}
}
}
});
}
});
You need to move loop from callback, into chart / events / load.
chart: {
events: {
load: function () {
var chart = this;
$.each(chart.series, function (i, serie) {
$.each(serie.data, function (j, data) {
if (data.yBottom - data.plotY < 15) data.dataLabel.hide();
});
});
}
},
renderTo: 'chart',
defaultSeriesType: 'bar'
},
Example: http://jsfiddle.net/HA5xE/20

Highcharts Legend titles changing after drilldown and back?

I have sample code for question here: http://jsfiddle.net/MuydK/
The problem relates to legend title in the key under chart are changing after I have drilled in and out.
They should stay as
"actual" and
"target"
And are changing to "series 1" and "series 2".
$(function () {
var chart;
$(document).ready(function () {
var colors = Highcharts.getOptions().colors,
categories1 = ['1011', '1112', '1213', '1415'],
name1 = 'Actual',
I think I may be missing something in drilldown configuration or setChart code?
I got the same problem with a couple if charts based on code posted above.
Many Thanks
Hope this is what you need,
JSFiddle - Legend Name Problem
code:
function setChart(name, categories, data, color) {
console.log(name, categories, data, color);
chart.xAxis[0].setCategories(categories);
while (chart.series.length > 0) {
chart.series[0].remove(true);
}
for (var i = 0; i < data.length; i++) {
chart.addSeries({
name: name[i],
data: data[i],
color: color[i]
});
}
}
Edit2: The problem is in your else statement in the function bellow.
click: function() {
var drilldown = this.drilldown;
if (drilldown) { // drill down
setChart(drilldown.name, drilldown.categories, [drilldown.data], drilldown.color);
} else { // restore
setChart(name, categories1, [data1, data2], 'white');
}
}​
Instead get rid of name1 = 'Actual' and only have data1 and data2 and add name and color to them then you could do like this instead
click: function() {
var drilldown = this.drilldown;
if (drilldown) { // drill down
chart.xAxis[0].setCategories(drilldown.categories);
setChart([drilldown.data]);
} else { // restore
chart.xAxis[0].setCategories(categories);
setChart([data1, data2]);
}
}
// add code for removing series
chart.addSeries({
data
});​
I hope you understand, but it will be easier if you build data1/2as a highcharts object, and just add the drilldown part to it. So you can change;
series: [{
name: name1,
data: data1,
color: colors[0]},
{
name: name2,
data: data2,
color: colors[1]}],
to:
series: [data1, data2],​
Edit: When you are doing operations bellow you should not set redraw to true, it will be much faster. The same goes for adding the series. You do not need to call chart.redraw() until you have removed and added the charts. And removing stuff is easier backwards. So change:
while (chart.series.length > 0) {
chart.series[0].remove(true);
}
To
for (var i = chart.series.length; i >= 0; i--){
chart.series[i].remove(false);
}
// add series with redraw == false
chart.redraw();

Resources