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
Related
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
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
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"
});
});
});
}
Here is the highchart demo of map with pie charts.
US map with pie charts
But this map is only for US. Here is my js fiddle.
World wide map with pie charts
// Add the pies after chart load, optionally with offset and connectors
Highcharts.each(chart.series[0].points, function (state) {
if (!state.id) {
return; // Skip points with no data, if any
}
var pieOffset = state.pieOffset || {},
centerLat = parseFloat(state.properties.latitude),
centerLon = parseFloat(state.properties.longitude);
// Add the pie for this state
chart.addSeries({
type: 'mappie',
name: state.id,
zIndex: 6, // Keep pies above connector lines
sizeFormatter: function () {
var yAxis = this.chart.yAxis[0],
zoomFactor = (yAxis.dataMax - yAxis.dataMin) /
(yAxis.max - yAxis.min);
return Math.max(
this.chart.chartWidth / 45 * zoomFactor, // Min size
this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes
);
},
tooltip: {
// Use the state tooltip for the pies as well
pointFormatter: function () {
return state.series.tooltipOptions.pointFormatter.call({
id: state.id,
hoverVotes: this.name,
demVotes: state.demVotes,
repVotes: state.repVotes,
libVotes: state.libVotes,
grnVotes: state.grnVotes,
sumVotes: state.sumVotes
});
}
},
data: [{
name: 'Democrats',
y: state.demVotes,
color: demColor
}, {
name: 'Republicans',
y: state.repVotes,
color: repColor
}, {
name: 'Libertarians',
y: state.libVotes,
color: libColor
}, {
name: 'Green',
y: state.grnVotes,
color: grnColor
}],
plotOptions: {
pie: {
center: [state.plotX+400, state.plotY]
}
}
}, false);
// Draw connector to state center if the pie has been offset
/* if (pieOffset.drawConnector !== false) {
var centerPoint = chart.fromLatLonToPoint({
lat: centerLat,
lon: centerLon
}),
offsetPoint = chart.fromLatLonToPoint({
lat: centerLat + (pieOffset.lat || 0),
lon: centerLon + (pieOffset.lon || 0)
});
chart.series[2].addPoint({
name: state.id,
path: 'M' + offsetPoint.x + ' ' + offsetPoint.y +
'L' + centerPoint.x + ' ' + centerPoint.y
}, false);
} */
});
I want to show map world wide map where each pie represent a country. Everything is working fine but world.js file dont have lat and long values.due to which i am facing positon issue of pie on each location.i tried using plotx and ploty .but it doesnt works. So is there any way to show pie axactly on the country area the way it is working US map?
You can use plotX & plotY properties of the region when it doesn't have the lat & lon defined.
Replace these two pieces of code:
plotOptions: {
pie: {
center: [state.plotX+400, state.plotY]
}
}
// Handle lat/lon support
if (options.center.lat !== undefined) {
var point = chart.fromLatLonToPoint(options.center);
options.center = [
chart.xAxis[0].toPixels(point.x, true),
chart.yAxis[0].toPixels(point.y, true)
];
}
with these ones:
center: {
plotX: state.plotX,
plotY: state.plotY
}
// Replace lat/lon with plotX/plotY
if (options.center.plotX !== undefined) {
options.center = [options.center.plotX, options.center.plotY];
}
By the way: using plotOptions inside series options is not valid. plotOptions should be placed in the top level of the chart options structure. Here's more info on that: https://api.highcharts.com/highcharts/plotOptions
Live demo: https://jsfiddle.net/BlackLabel/k5mdL6vn/
I need to display multiple pie charts that are all related to the same data. As such I want them all to be part of the same chart and implement them as individual series.
This all works no problems until I tried to put labels/titles over each individual pie chart. It seems that I can only have a title over the entire group. See jsfiddle
Is there any way to have the titles over each chart?
See above jsfiddle for example
I encountered the same problem, and found this solution via highcharts support forum :
http://highcharts.uservoice.com/forums/55896-general/suggestions/3073133-pie-title
The Highcharts dude has written a plugin that you can see working on the following jsfiddle : http://jsfiddle.net/highcharts/tnSRA/
I have copy-pasted this plugin in a highcharts-plugins.js file that I included in my website, works like a charm!
Here's the plugin code :
/**
* Pie title plugin
* Last revision: 2012-12-21
*/
(function (Highcharts) {
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
var chart = this.chart,
center = this.center || (this.yAxis && this.yAxis.center),
titleOption = this.options.title,
box;
proceed.call(this);
if (center && titleOption) {
box = {
x: chart.plotLeft + center[0] - 0.5 * center[2],
y: chart.plotTop + center[1] - 0.5 * center[2],
width: center[2],
height: center[2]
};
if (!this.title) {
this.title = this.chart.renderer.label(titleOption.text)
.css(titleOption.style)
.add()
.align(titleOption, null, box);
} else {
this.title.align(titleOption, null, box);
}
}
});
}(Highcharts));
And this is how you configure your title (put this in your series elements) :
title: {
// align: 'left',
// x: 0
// style: { color: XXX, fontStyle: etc }
text: '<b>Pie 1</b><br>Subtext',
verticalAlign: 'top',
y: -40
},
To further improve on this, the code below correctly handles left, center, and right justification for the titles. See fiddle at http://jsfiddle.net/9y4Lj4yr/ for an example.
/**
* Pie title plugin
* Last revision: 2015-5-20
*/
(function (Highcharts) {
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
var chart = this.chart,
center = this.center || (this.yAxis && this.yAxis.center),
titleOption = this.options.title,
box;
proceed.call(this);
if (center && titleOption) {
box = {
x: chart.plotLeft + center[0] - 0.5 * center[2],
y: chart.plotTop + center[1] - 0.5 * center[2],
width: center[2],
height: center[2]
};
if (!this.title) {
this.title = this.chart.renderer.label(titleOption.text)
.css(titleOption.style)
.add()
}
var labelBBox = this.title.getBBox();
if (titleOption.align == "center")
box.x -= labelBBox.width/2;
else if (titleOption.align == "right")
box.x -= labelBBox.width;
this.title.align(titleOption, null, box);
}
});
} (Highcharts));
You can use renderer which allows to add text in any place.
http://api.highcharts.com/highcharts#Renderer.text()
Improving on Vincent's answer. This is how I used it for simple Text titles.
extendHighcharts = function(){
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
//Clear the title if added previously
//if your chart data does not change, this reference storage for removal can be left out
if(this.chart.subChartTitleElement){
this.chart.subChartTitleElement[this.id].destroy();
}
proceed.call(this);
if (this.center && this.options.title) {
//first, add the title, at center or anywhere, we need the container width to center it
this.chart.subChartTitleElement[this.id] = this.chart.renderer.text(this.options.title.text,this.center[0],this.center[1]);
this.chart.subChartTitleElement[this.id].css(this.options.title.style)
this.chart.subChartTitleElement[this.id].add();
//Center the title using the container(Bounding Box = BBox) width
var xCenter = this.chart.plotLeft + this.center[0] - (this.chart.subChartTitleElement[this.id].getBBox().width/2),
yCenter = this.chart.plotTop + this.center[1] - 0.6 * this.center[2];
this.chart.subChartTitleElement[this.id].attr(
{
x:xCenter,
y:yCenter
}
);
}
});
}
USAGE
this.chart.addSeries({
type: 'pie',
name: 'pie_chart_1',
data: pieChartData,
center: ['80%','25%'],
size: '35%',
showInLegend: false,
dataLabels: {
enabled: false
},
//this part adds the relevant information
title: {
text:'Pie Chart Title',
verticalAlign: 'top',
y: -40
},
id:'a_unique_id_or_name'
});