I am trying to set min, max on chart1(yAxis) by clicking setExtremes button, But it works only on chart3(yAxis).
const A = {
setYaxis: 0,
titleText: 'chartOne'
};
const B = {
setYaxis: 1,
titleText: 'chartTwo'
};
const C = {
setYaxis: 2,
titleText: 'chartThree'
};
I set both titleText and setYaxis on yAxis.
titleText works, but setYaxis does not work.
yAxis :[{
title: {
text: item.titleText
},
yAxis: item.setYaxis
}],
Trying to set for chart1, but this sets for chart3
$('#minmax').click(function(){
console.log("minmax")
chart1.yAxis[0].setExtremes(8, 10);
});
Fiddle: https://jsfiddle.net/jkfren2L/21/
I face the same issue for plotlines as well. Now they appear only on last chart.
Thank you.
That's because after the loop the chart1 variable refers to the last created chart. You can store charts in an array. Moreover, to make all y-extremes synchronized, you need to call the syncExtremes function on setExtremes event from yAxis.
yAxis: [{
...,
events: {
setExtremes: syncExtremes
}
}]
If it comes to the plot-lines, they are hidden because of the following setting:
xAxis: {
visible: i === items.length - 1,
...
}
You should hide only xAxis labels:
xAxis: {
labels: {
enabled: i === items.length - 1,
format: '{value} time'
},
...
}
Live demo: https://jsfiddle.net/BlackLabel/9xLwa87q/
API Reference: https://api.highcharts.com/highcharts/xAxis
I'm able to create and configure the series of a Pie chart using the following code:
createPieChart() {
this.options.series = [{
type: 'pie',
labelKey: 'os',
angleKey: 'share',
label: { enabled: true },
}]
this.options.legend = { enabled: false }
},
The labels appear like so, which means that if the label is too long it overflows both onto the chart itself and over the sides of the div it's being contained within:
I am aiming to make it so that if the label has more than 5 characters then it would only show 3 characters and the following symbols: ...
So for example, the label 'Symbian qwerfrwf wfegewdfv fewdf feewdf' for the blue section of the pie chart above would only show 'Sym...'
I know how to do this for column and bar charts where we use a formatter
label: {
formatter: (params) => {
if (params.value.length > 5) {
return params.value.substr(0, 3) + '...';
}
return params.value;
},
}
However, for a pie chart there doesn't seem to be a formatter available in the documentation (API Reference) (https://www.ag-grid.com/javascript-charts-pie-series/)
How can I achieve the style I want for pie chart labels?
legend: {
enabled: true,
item:{
label:{
formatter:(params)=>{
console.log('id',params.id)
console.log('itemId',params.itemId)
console.log('value',params.value)
return 'my legend goes here'
}
}
}
},
Hi I am trying to present the columns values at the top of each column so it is easier for the user to compare values.
I have got this working but when some columns are very close to each other some of the values aren't being dispalyed because I'm presuming highcharts works out that it wqouldnt fit unless it overlapped so it doesnt show the value.
Here is the code for my chart -
var chart_1_Options = {
chart: {
renderTo: 'container_chart_1',
backgroundColor: '#FFFFFF'
},
credits: {
enabled: false
},
title: {
text: ''
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
}
},
plotOptions: {
column: {
animation: false,
borderWidth: 0,
dataLabels: {
enabled: true,
formatter: function() {
return '<p style="font-size: 8px;">' + this.y + '% </p>';
}
}
}
},
legend: {
enabled: true
}
};
Here is an image of what the chart looks like, I have circled areas where the value is missing
I just want the value to show even if it can't fit, I want it to place the value somewhere inside the column if it cant fit at the top.
Thanks for any help!
I think that you can try to find those labels and show them by doing something like code below:
events: {
load() {
let chart = this;
chart.series[0].points.forEach(p => {
setTimeout(function() {
if (p.dataLabel.translateY === -9999) {
p.dataLabel.translate(p.dataLabel.alignAttr.x, p.dataLabel.alignAttr.y + 20)
p.dataLabel.css({
opacity: 1
})
}
}, 50)
})
}
}
Demo: https://jsfiddle.net/BlackLabel/unzgsmfr/
API: https://api.highcharts.com/highcharts/chart.events.load
I have multiple charts on the same page, and the goal was to have same max values for each of the metrics on all charts to make comparison of charts easier ( https://www.screencast.com/t/vtF6h5ZRWS )
I've tried with max values and min values, but it doesn't works, probably because of multiple y-axises.
Now I'm trying to use tickpositions (which I'm calculating in backend) and passing it to chart. But here is the problem with tick alignment on opposite axes and it appears as shown https://www.screencast.com/t/iwnGOhJFb
Below is the small part of code how I set the tick positions and the fiddle of simpler version of chart that I have (I had more y axis's)
yAxis: [{ // Primary yAxis
labels: {
format: '{value}',
style: {
color: Highcharts.getOptions().colors[2]
}
},
title: {
text: 'Impressions',
style: {
color: Highcharts.getOptions().colors[2]
}
},
tickPositions: [0, 5500000, 11000000, 15000000]
}
http://jsfiddle.net/j82oen9c/8/
How can I achieve tick alignments on all y-axis's ?
In order to align the ticks on both axes, you can use two different approaches.
FIrst one is by define your own Axis.tickPositioner function which returns calculated array of tickcs adjusted to your needs.
Moving on, you need to get the same amount of ticks on both axes, and they should lay on the same positions on axes, so the positioner function should receive two arguments - maxValueOfCurrentAxis and tickAmount. I wrote the function like that:
var positioner = function(tAmount, axisMax) {
var positions = []
for (var i = 0; i < tAmount; i++) {
positions.push(Math.round(((axisMax / tAmount) * i) * 100) / 100)
}
positions.push(axisMax)
return function() {
return positions
}
}
and now, we need to assign this function with specific parameters as the Axis.tickPositioner, and define the amount of ticks and max values of both axes:
var tickAmount = 3
var firstAxisMax = 15000000
var secondAxisMax = 2
yAxis: [{ // Primary yAxis
labels: {
format: '{value}',
style: {
color: Highcharts.getOptions().colors[2]
}
},
title: {
text: 'Impressions',
style: {
color: Highcharts.getOptions().colors[2]
}
},
tickPositioner: positioner.apply(this, [tickAmount, firstAxisMax]),
}, { // Secondary yAxis
gridLineWidth: 0,
tickPositioner: positioner.apply(this, [tickAmount, secondAxisMax]),
title: {
text: 'eCPM',
style: {
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value} $',
style: {
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
Live example: http://jsfiddle.net/vL324nqx/
The second way out of that issue, but not so much adjusted to your needs, is by using Axis.tickPixelInterval property on both axes. There is no need to explain it more precisely, because there are clear informations about that in API.
Live example: http://jsfiddle.net/mqget4hb/
API Reference:
https://api.highcharts.com/highcharts/yAxis.tickPositioner
https://api.highcharts.com/highcharts/yAxis.tickPixelInterval
I am trying to plot a categorical multi axis column chart of rankings. The number 1 ranking should be the tallest column and lowest ranking the shortest.
Essentially I would like the height of the bar to be it's reciprocal.
It is very close to:
var player_name_array = ["Aaron Rodgers", "Andrew Luck", "Drew Brees", "Russell Wilson", "Peyton Manning", "Ryan Tannehill", "Tony Romo", "Matt Ryan", "Cam Newton", "Ben Roethlisberger", "Eli Manning", "Philip Rivers", "Colin Kaepernick", "Teddy Bridgewater", "Marcus Mariota", "Matthew Stafford", "Robert Griffin III", "Joe Flacco", "Jay Cutler", "Sam Bradford"];
var series_array = [{"name":"espn_ranking","data":[38,33,63,64,67,95,75,85,96,76,999,999,999,999,999,999,999,999,999,999]}];
rankings_chart = new Highcharts.Chart({
chart: {
renderTo:'rankings_chart',
type: 'column'
},
title: {
text: 'Draft Rankings'
},
subtitle: {
text: 'Source: The Internet'
},
xAxis: {
categories: player_name_array,
crosshair: true
},
yAxis: {
type: 'logarithmic',
//reversed: true,
title: {
text: 'Draft Rankings'
}
},
tooltip: {
headerFormat: '<span style="font-size:14px"><b>{point.key}</b></span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y}</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
series: {
stacking:'normal',
},
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
rangeSelector: {
selected: 1
},
series: series_array
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="rankings_chart" ></div>
The problem with this is the columns come down from the top and ranking of 1 is still the smallest column.
Is there any way to add a function for the height of each column?
Set up your data to be the inverse of the player ranking:
var rankings = [38,33,63,64,67,95,75,85,96,76,999,999,999,999,999,999,999,999,999,999]
var inv_rankings = [];
for (i = 0; i < rankings.length; i++) {
inv_rankings[i] = 1 / rankings[i]
}
Set your Highcharts data to be your inverse ranking:
series: {
name: "espn_ranking",
data: inv_rankings
}
Use a formatter for the data labels and tooltip to return the reciprocal of the reciprocal (i.e. the original value):
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter: function() {
return 1 / this.y;
}
}
},
tooltip: {
pointFormatter: function() {
return 1 / this.y;
}
}
}
Working fiddle
This was an interesting and fun puzzle to work out!
I thought the answer by nagyben was an excellent one, and I based my code on their method of inversing the scores to come up with a relative rank.
Here's a working fiddle I created based on that concept, along with several enhancements, which I've shared below: https://jsfiddle.net/brightmatrix/j4ug40qm/
I added a sort function to rank the data in descending order, no matter how the data were arranged in the original two arrays. In order to do this, I first combined both arrays into a single Javascript object.
I changed the format to a column (vertical) chart to a bar (horizontal) chart. This will make the player names more readable for your users.
I updated the tooltip to show the player's rank whenever a user hovers their cursor over a particular bar.
I removed certain chart elements that aren't needed in this kind of chart, such as the legend, gridlines, and axis labels (since you're simply doing a rank, the true value of each bar isn't relevant to the user).
Here's the sort code that I built into this:
// combine both arrays into a single object so we can then sort them by rank
var rankArray = [];
$.each(player_name_array, function(index) {
tempArray = {};
tempArray['name'] = player_name_array[index];
tempArray['y'] = 1 / series_array[index];
rankArray.push(tempArray);
});
// sort the objects by rank (the "y" value) in descending order (due to the inverse)
// see accepted answer by Stobor at:
// http://stackoverflow.com/questions/979256/sorting-an-array-of-javascript-objects
rankArray.sort(function(a, b) {
return parseFloat(b.y) - parseFloat(a.y);
});
And here's the updated chart options:
rankings_chart = new Highcharts.Chart({
chart: {
renderTo:'rankings_chart',
type: 'bar' // chose a bar vs. column chart so the player names are easier to read
},
title: { text: 'Draft Rankings' },
subtitle: { text: 'Source: The Internet' },
legend: { enabled: false }, // there is no legend needed for this chart
xAxis: {
type: 'category',
tickmarkPlacement: 'on' // place the lines directly on the player's name
},
yAxis: {
// we're measuring by rank, so there's no need for labels, gridlines, or a title
labels: { enabled: false },
title: { enabled: false },
gridLineWidth: 0
},
tooltip: {
pointFormatter: function() {
// show the rank of the player, based on their sort order
return 'ranked #' + parseInt(this.x+1);
}
},
plotOptions: {
bar: {
groupPadding: 0.1,
pointPadding: 0.2,
borderWidth: 0
}
},
series : [{
name : 'Draft Data',
data : rankArray // our array will look like this: [{name: 'NAME', y: 0}, ...]
}]
});
Here's the result:
I hope this has been helpful to you in your chart conversion.
Since you seem to already have set an upper limit of 999 for your data, i would suggest simply plotting 1000-x.
One way to do that is to let highcharts do the math in a function for the series:
series : [{
name : 'Draft Data',
data : (function () {
// generate an array of random data
var data = [];
for (var x = 0;x <= series_array.length; x += 1) {
data.push([
1000-series_array[x];
]);
}
return data;
}())
}]
JSFiddle: http://jsfiddle.net/hmjnz/4/
In this case i would hide the yaxis label and instead put annotations on the columns with the rank.
Alternatively i'd debate whether a column chart is an adequate representation for this type of data.