If i have large amount of data then data labels are overlapping. how to add spacing between data labels in this case .
[
https://jsfiddle.net/3ekhdqov/1/][1]
There is no built-in logic for anit-collision data labels, but you can implement some, according to your needs. You can for example edit translateY attribute based on point's y value.
chart: {
zoomType: 'xy',
events: {
render: function() {
var series = this.series;
series[0].points.forEach(function(point, index) {
if (Math.abs(series[1].points[index].y - point.y) < 20) {
console.log(point.dataLabel)
point.dataLabel.attr({
translateY: point.dataLabel.y + 20
});
}
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/bg0eyh2t/
API Refernece: https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
Related
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
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
I try to get a synced crosshair for multiple highcharts each with a different width.
For know the crosshair is syncing on the position of the cursor and not on the position of the point / the xAxis value (which would be prefered). Can anyone give me a hint how to achieve this?
I have changed the synced charts example in the following fiddle:
https://jsfiddle.net/3mn4x8uy/
The chart creation:
$.each(activity.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40+i*100, // make different width for each chart
spacingTop: 20,
spacingBottom: 20
},
sync code
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
// Find coordinates within the chart
event = chart.pointer.normalize(e.originalEvent);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
Thanks
Here you can find an example how to synchronize multiple charts based on xAxis value: http://jsfiddle.net/BlackLabel/udtkgs9m/
The code to sync a Plotline over multiple Charts:
function syncronizeCrossHairs(chart) {
var container = jQuery(chart.container),
offset = container.offset(),
x, y;
container.mousemove(function(evt) {
x = evt.clientX - chart.plotLeft - offset.left;
y = evt.clientY - chart.plotTop - offset.top;
var val = chart.xAxis[0].translate(x, true);
Highcharts.each(Highcharts.charts, function (act_chart) {
var xAxis = act_chart.xAxis[0];
xAxis.removePlotLine("myPlotLineId");
xAxis.addPlotLine({
value: val,
width: 1,
color: 'red',
//dashStyle: 'dash',
id: "myPlotLineId"
});
});
});
}
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
I have tens of thousands (possibly hundreds of thousands) of points that I need plotted with Highcharts. Is there a way where I can cluster the data on the server, so it will show less than 1000 points, but as you zoom in it will make AJAX calls to the server to get the data for that zoomed region (it would probably run through the same cluster algorithm). How would this interface with the Highcharts API?
There is a highstock demo that does this http://www.highcharts.com/stock/demo/lazy-loading.
But you can do the same thing with highcharts http://jsfiddle.net/RHkgr/
The important bit is the afterSetExtremes function
...
xAxis : {
events : {
afterSetExtremes : afterSetExtremes
},
...
/**
* Load new data depending on the selected min and max
*/
function afterSetExtremes(e) {
var url,
currentExtremes = this.getExtremes(),
range = e.max - e.min;
var chart = $('#container').highcharts();
chart.showLoading('Loading data from server...');
$.getJSON('http://www.highcharts.com/samples/data/from-sql.php?start='+ Math.round(e.min) +
'&end='+ Math.round(e.max) +'&callback=?', function(data) {
chart.series[0].setData(data);
chart.hideLoading();
});
}
Here is an improvement for Barbara's answer,
It registers to the setExtremes event,
to know if this is a reset zoom event.
If it is - it gets the entire dataset,
thus allowing reset zoom to work correctly.
It also allows zooming in both x and y.
http://jsfiddle.net/DktpS/8/
var isReset = false;
...
xAxis: {
events: {
afterSetExtremes : afterSetExtremes,
setExtremes: function (e) {
if (e.max == null || e.min == null) {
isReset = true;
}
else
{
isReset = false;
}
}
},
minRange: 3600 * 1000 // one hour
},
series: [{
data: data,
dataGrouping: {
enabled: false
}
}]
});
});
});
/**
* Load new data depending on the selected min and max
*/
function afterSetExtremes(e) {
var url,
currentExtremes = this.getExtremes(),
range = e.max - e.min;
var chart = $('#container').highcharts();
var min = 0;
var max = 1.35e12;
if(!isReset)
{
min = e.min;
max = e.max;
}
chart.showLoading('Loading data from server...');
$.getJSON('http://www.highcharts.com/samples/data/from-sql.php?start=' + Math.round(min) +
'&end=' + Math.round(max) + '&callback=?', function (data) {
chart.series[0].setData(data);
chart.hideLoading();
});
}
In case when you will not have a limit of points, you can increase turboThreshold paramter.