I'm trying to add a custom label to a highcharts pie chart. The label is going to (eventually) be center, bottom aligned and display some html data. The problem is the label does not show on the chart, trying to use 'renderer'. I'm quite new to highcharts, what am I doing wrong?
$('#div_graph_0_1').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
credits: {
enabled: false
},
title: {
text: 'NEW VISITORS'
},
subtitle:{
text: pieSubtitleTotal,
style: { color: '#f07600' }
},
tooltip: {
pointFormat: '{point.y}'
},
plotOptions: {
pie: {
states: {
hover: {
halo: {
size: 9,
attributes: {
fill: '#f07600'}
}
}
},
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
connectorWidth: 0,
enabled: true,
format: '{point.y}',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
},
}
},
series: [{
name: 'New',
colorByPoint: true,
data: [{
name: 'Repeat',
y: subtitleTotal,
color: '#fff',
borderColor: '#f07600',
borderWidth: 2
}, {
name: 'New',
color: '#f07600',
borderColor: '#f07600',
y: pieTotalVisitors,
sliced: true,
selected: true
}]
}],
navigation: {
buttonOptions: {
enabled: false
}
},
function(chart) { // on complete
chart.renderer.text('This text is <span style="color: red">styled</span> and linked', 0, 0)
.css({
color: '#4572A7',
fontSize: '16px'
})
.add();
}
});
You're on the right track, as your rendered text IS there and present on the chart. What you needed to define was the expected X and Y values where you wanted the text to be placed.
I discovered this because of the "y" in "styled":
If you define a different y value in your renderer.text call, say, 100, you get this:
Here is the syntax you should follow:
chart.renderer.text('Your text', X_VALUE, Y_VALUE)
In my above example, I set your text to:
chart.renderer.text('Your text', 0, 100)
... which puts it 100 pixels down from the top of the chart.
You're going to have to define these values manually; there's no out-of-the-box way to say "bottom-aligned, center-aligned." To make this more versatile, what you could do is capture the height and width of your container div and calculate the x and y values that way.
You can do this by fixing the height and width of your chart in a stylesheet declaration, defining JavaScript variables outside your chart options, and then calling those variables from the renderer.text declaration:
// in your inline stylesheet
#container: { width: '650px', height: '450px' }
// variables defined before your chart options
var chartHeight = $('#container').height();
var chartWidth = $('#container').width();
// in your renderer code
chart.renderer.text('Your text', chartWidth * 0.5, chartHeight - 100)
In the above example, your rendered text would start at 50% of your chart's width and 100 pixels from the bottom of your chart.
One point to keep in mind: you mentioned an HTML table. In that case, I'd suggest switching renderer.text to renderer.html. That will allow many more HTML elements to be rendered in the final chart.
I hope all of this has been helpful!
Related
I am trying to achieve combined 2 Semidonut Pie Charts series to show Current year and Last year percentage with my data .
At the same time I am trying to overlay another series with data which will represent the YOY percentage increase or decrease which will appear as label outside my outer pie as "+50%" , "-60%"
Since YOY can be negative and this disturb's the Pie . I was reading that Pie is not ideal to put the negative numbers but visually in my usecase customer feels this will be great .
I tried to massage the YOY data with negative to multiply with (-1) and put into pie and I kind of able to represent the number outside pie but can't bring the "+" or "-" with "%" as valuesuffix .
I have working example here but again this is with 2 data series ... my 3rd series will be "YOY%" with the datalabel display outside which is not added here as 3rd series with negative bring a weird donut .
Anybody has idea how to implement this solution to represent series 3 with YOY Outside as regular datalabels ?
https://codepen.io/pauldx/pen/BayyJaa
Highcharts.chart('container', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: 0,
plotShadow: false
},
title: {
text: 'Browser<br>shares<br>2017',
align: 'center',
verticalAlign: 'middle',
y: 60
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
dataLabels: {
enabled: true,
distance: -50,
style: {
fontWeight: 'bold',
color: 'white'
}
},
startAngle: -90,
endAngle: 90,
center: ['50%', '75%'],
size: '110%'
}
},
series: [{
type: 'pie',
innerSize: '50%',
dataLabels: {
enabled: true,
// inside: true,
distance: -70,
},
data: [
['LYA', 58.9],
['LYB', 28.9],
['LYC', 30.29],
]
},
{
type: 'pie',
name: 'Browser share',
innerSize: '70%',
dataLabels: {
enabled: true,
// inside: true,
distance: -20,
},
data: [
['CYA', 20],
['CYB', 18.9],
['CYC', 70.29],
]
}]
});
As I understood - you would like to add only the dataLabels with calculated YOY value, am I right? Or do you want to add a whole series? If just a dataLabels - there is a guideline how to achieve it by adding custom dataLabels:
events: {
render() {
let chart = this,
yoyValue,
x,
y;
chart.series[1].points.forEach((p, i) => {
if (chart['label' + i]) {
chart['label' + i].destroy();
}
yoyValue = Math.floor(((p.y - chart.series[0].points[i].y) / p.y) * 100);
x = p.dataLabel.translateX - (p.shapeArgs.end == 0 ? -40 : 30);
y = p.dataLabel.translateY;
chart['label' + i] = chart.renderer.text(yoyValue + '%', x, y).attr({
zIndex: 100,
}).css({
fontWeight: 'bold',
color: 'white',
textOutline: '1px contrast'
}).add();
})
}
}
Demo: https://jsfiddle.net/BlackLabel/p82L4ad1/1/
API: https://api.highcharts.com/highcharts/chart.events.render
API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
I want to make a chart like this in highchart. How can I add the yellow colored box in my chart
It can be made by adding additional x-axes (in a bar chart x-axes are vertical ones) and setting them as opposite and linked to the main axis. Check the code and demo posted below and let me know if something is unclear to you.
Code:
const defaultLabelOptions = {
opposite: true,
linkedTo: 0,
lineWidth: 0,
tickWidth: 0
};
const defaultAxisTitleOptions = {
align: 'high',
rotation: 0,
margin: 0,
textAlign: 'center',
style: {
'text-decoration': 'underline',
'font-weight': 'bold'
}
};
// ...
xAxis: [{
categories: ['Africa', 'America', 'Asia', 'Europe', 'Oceania'],
title: {
text: null
}
}, {
...defaultLabelOptions,
offset: 50,
labels: {
align: 'right',
formatter: function() {
return labels.le[this.value];
}
},
title: {
text: 'LE',
...defaultAxisTitleOptions
}
}, {
...defaultLabelOptions,
offset: 110,
labels: {
align: 'right',
formatter: function() {
return labels.tgt[this.value];
}
},
title: {
text: 'TGT',
...defaultAxisTitleOptions
}
}]
Demo:
https://jsfiddle.net/BlackLabel/68hdutxv/
API reference:
https://api.highcharts.com/highcharts/yAxis.opposite
https://api.highcharts.com/highcharts/yAxis.linkedTo
If you want to have lines between the additional axes you can add them using Highcharts.SVGRenderer: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer
I have a series that I would like to be ignored in the percentage calculation of a pie chart but still be shown/hidden when the legend item is clicked. The series represents the total and should always be 100%. If I set visible to false for the series it is initially hidden in the chart and the legend item is greyed out. However, clicking the legend item shows the series with the calculated percentage. It seems like I need another series behind the values I would like to be calculated and displayed, that's always 100%, any ideas?
Thanks!
Chart Config
vm.installationResultsConfig = {
options: {
exporting: {
type: 'application/pdf',
filename: 'installation-results'
},
credits: {
enabled: false
},
navigation: {
buttonOptions: {
enabled: false
}
},
chart: {
backgroundColor: '#F9F9F9',
borderColor: '#eee',
plotBackgroundColor: null,
plotBorderWidth: 0,
plotShadow: false,
height: 440
},
title: {
text: 'Installation Results',
align: 'center',
verticalAlign: 'top'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
dataLabels: {
enabled: false
},
startAngle: 0,
endAngle: 360,
center: ['50%', '55%'],
showInLegend: true
}
},
legend: {
align: 'left',
verticalAlign: 'middle',
layout: 'vertical',
x: -8,
y: 30,
labelFormatter: function () {
if(this.name === 'All Vehicles') {
this.percentage = 100;
}
return '<span>' + this.name + '</span><br />' +
'<span>' + this.dataLabels.count + '</span><br />' +
'<span>' + $filter('number')(this.percentage) + '%</span>';
},
useHTML: true,
itemMarginTop: 5,
itemMarginBottom: 5
}
},
series: [{
type: 'pie',
name: 'Installation Results',
innerSize: '70%',
data: [
{
name: 'All Vehicles', // should be ignored and alway render as 100%
y: chartData.allVehicles,
color: '#999999',
dataLabels: {
count: $filter('number')(chartData.allVehicles)
}
},
{
name: 'Successful',
y: chartData.successful,
color: '#50CF63',
dataLabels: {
count: $filter('number')(chartData.successful)
}
},
{
name: 'Failed',
y: chartData.failed,
color: '#F22F1D',
dataLabels: {
count: $filter('number')(chartData.failed)
}
},
{
name: 'Not Attempted',
y: chartData.notAttempted,
color: '#296499',
dataLabels: {
count: $filter('number')(chartData.notAttempted)
}
}
]
}]
};
The percentage property will affect all pie slices in series. In that situation, you can create custom percentage property, which will be calculated based only on visible slices that are not 'All Vehicles' slice. Take a look at the example below. Also, I think that the labelFormatter function is not the right place to make calculations but I only wanted to show you the idea.
Example:
http://jsfiddle.net/g1hw761h/
How can i draw following graph using Scatter Plot highchart?
I am trying to achieve this kind of plot that is being displayed in screenshot using Highcharts. Till now I am able to Draw point onto the chart using Scatter Plot but I am having trouble plot these two red line from X-axis and Y-axis. Can anyone of you help me here the what I need to do to draw two straight line from a point, one toward X-axis and second toward Y-axis. The attached code is only the JS code that I used for ploting the scatter graph. Thanks
/* calculationChart */
$(function () {
$('#FHIchart').highcharts({
chart: {
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Height Versus Weight of 507 Individuals by Gender'
},
subtitle: {
text: 'Source: Heinz 2003'
},
xAxis: {
title: {
enabled: true,
text: 'Strategic Alignment'
},
startOnTick: true,
endOnTick: true,
showLastLabel: true,
},
yAxis: {
title: {
text: 'Process & Technology Integration'
},
},
legend: {
layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF',
borderWidth: 1
},
plotOptions: {
scatter: {
lineWidth: 2
}
},
series: [{
name: ' ',
color: 'Red',
data: [[3.1, 3]]
}]
});
});
here is my code.
Use renderer.path to draw a line. You can draw the line on load event and redraw it on redraw event.
events: {
load: function() {
var point = this.series[0].points[0],
{
plotX: x,
plotY: y
} = point;
point.path = this.renderer.path()
.add(point.series.group)
.attr({
stroke: point.color,
'stroke-width': 1,
d: `M 0 ${y} L ${x} ${y} L ${x} ${this.plotHeight}`
});
},
redraw: function() {
var point = this.series[0].points[0],
{
plotX: x,
plotY: y
} = point,
path = point.path;
if (path) {
path.attr({
d: `M 0 ${y} L ${x} ${y} L ${x} ${this.plotHeight}`
})
}
}
}
example: https://jsfiddle.net/5j208Lpb/
The other solution is to define 2 additional points which will have be drawn outside the plot area. You need to set axes limits and set series.lineWidth to 1.
example: https://jsfiddle.net/5j208Lpb/1/
I am generating my x-axis and y-axis data dynamically and displaying highcharts, but the chart becomes messy when the x-axis range is high with small intervals.
How do I make highcharts to make normal horizontally scrollable graph?
Here is what I am using right now:
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
//CODE FOR HIGHCHARTS JS
function makeChart() {
$('#container').highcharts({
chart: {
type: 'line',
marginRight: 130,
marginBottom: 100
},
title: {
text: 'Banana',
x: -20 //center
},
subtitle: {
text: 'Source: banana.com',
x: -20
},
xAxis: {
categories: xlist
},
yAxis: {
title: {
text: 'No. of C'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: 'C'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [{
name: $("#repoSelector option:selected").text(),
data: ylist
}]
});
}
Two ways to achieve a scroll bar.
Option 1
You will need to use highstock.js and instead of rendering a stock chart, you have to render a highchart.
Then enable the scroll bar
scrollbar: {
enabled: true
}
Check the API for scroll bar and related operations here.
Here I have fiddled an example.
Option 2
Try setting min & max attributes to the x-axis.
xAxis: {
categories: [...],
min: 0,
max:9
}
Displays 10 categories in x-axis at a stretch, adding a scroll for the rest of the categories.
find the fiddled example here.
To enable scrollbar in x-axis, try this
xAxis: {
categories: xlist,
min: 0,
max: 4,
scrollbar: {
enabled: true
},
},
Check the jfiddle here: https://jsfiddle.net/BhavyaAprajita/zja90wf2/1/
Also, make sure that you import the highstock library
src="https://code.highcharts.com/stock/highstock.js"
add this
const Highcharts = require('highcharts/highstock');
comment this if you have
// import Highcharts from 'highcharts';
change xAxis to like this
xAxis : {
categories: [],
min:0,
max:9,
scrollbar: {
enabled: true
}
}
Use
require('highcharts/highmaps') instead of require('highcharts') in imports<br>
#NgModule({<br>
...<br>
imports: [<br>
BrowserModule, <br>
ChartModule.forRoot( <br>
require('highcharts/highmaps')<br>
],<br>
})