there are a few questions about stacklables on SO, but I don't see any related to my question.
Right now, I have a pretty standard column chart (built with HighCharts). It has basic stack labels and everything works fine. However, when a user expands the viewset of the data (in essence expanding the size of the series) the StackLabels (labels above individual columns) overlap and look messy.
So, I want to hide the stack labels for all columns when the series is say >= 20.
Right now, my stack labels are shown like this:
yAxis: {
min: 0,
title: {
text: 'My Title'
},
stackLabels: {
enabled: true,
formatter: function () {
//if more than 20 points, hide them
if (this.series.length >= 20) {
return ''
}
//else show them
return this.total
}
},
But this doesn't work because the context for 'this' isnt correct, thus this.series.[anything] returns undefined. It seems 'this' is referring to the point..but I need to reference the chart that contains the point.
Is this possible?
This in the formatter does not refer to the chart object nor the axis. Also, data from the series is not yet available. However, you can get the length of the data from the options.
formatter: function() {
//if more than 20 points, hide them
if (this.axis.series[0].options.data.length >= 20) {
return false
}
//else show them
return this.total
}
example: http://jsfiddle.net/6mmLu3ct/
Related
I've already figured out how to make a chart using highcharts where there are three variables- one on the X axis, one on the Y axis, and one on the tooltip. The way to do this is to add the following to the tooltip:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
const pointData = chartData.find(row => row.timestamp === this.point.x)
return pointData.somethingElse
}
}
See this fiddle for the full code:
https://jsfiddle.net/m9e6thwn/
I would simply like to do the same, but with two series instead of one. I can't get it to work. I tried this:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
const pointData = chartData1.find(row => row.timestamp === this.point.x)
return pointData.somethingElse
const pointData2 = chartData2.find(row => row.timestamp === this.point.x)
return pointData2.somethingElse
}
}
Here is the fiddle of the above: https://jsfiddle.net/hdeg9x02/ As you can see, the third variable only appears on one of the two series. What am I getting wrong?
There are some issues with the way you are using the formatter now. For one, you cannot have two returns in the same function without any if clauses. That will mean that only the first return will be used.
Anyway, here are some improvements I suggest you do for your code.
Add the extra information for each point to highcharts, that makes it a lot easier to access this information through highcharts. E.g. in a tooltip. You can set the data like this:
chartData1.map(function(row) {
return {
x: row.timestamp,
y: row.value,
somethingElse: row.somethingElse
}
})
If you do that, then returning the correct tooltip for each series is a simple matter of doing this:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
return this.point.somethingElse
}
}
Working JSFiddle example: https://jsfiddle.net/ewolden/dq7L64jg/6/
If you wanted more info in the tooltip you could then do:
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
return this.point.somethingElse + ", time: " + str(this.x) + ", value: " + str(this.y)
}
}
Addtionally, you need to ensure that xAxis elements, i.e. your timestamps are sorted. This is a requirement for highcharts to function properly. As it is, your example is reporting
Highcharts error #15: www.highcharts.com/errors/15
in console, because chartData2 is in reverse order. It looks okay for this example, but more complicated examples can lead to the chart not looking as you expect it to.
For this example using reverse is easy enough: data: chartData2.reverse().map(function(row) {return {x: row.timestamp, y: row.value, somethingElse: row.somethingElse}})
Working JSFiddle example: https://jsfiddle.net/ewolden/dq7L64jg/7/
I created a scatter chartlike this in the JSfiddle (http://jsfiddle.net/q8h39/102/)
which is doing two dimension data analysis.
but I need to contain some extra information (e.g: custom names and a extra count value) in the chart** and give different color for each of the plots.
I tried to create an Array and use the tooltip library like this but i didn't reach the goal yet still.
var nameArr = ['anson','jason','samson','dickson']; // Names
tooltip: {
format: {
title: function (d) { return nameArr; },
}
}
Please see the JSfiddle code for further details, many thanks
The below is the current result and the exception exception after development
i have gone through the jsfiddle link and there were two issue with this:-
c3js library is old
c3js does not provide this functionality out of the box but you can achieve this using trick.
I have fixed both of above given issues and now it is working fine.
jsfiddle:-
http://jsfiddle.net/q8h39/109/
code for setting the tooltip:-
tooltip: {
format: {
title: function(x) {
var indOfVal = engagmentArr.indexOf(x);
return nameArr[indOfVal - 1]
},
name: function() {
return engagmentArr[0];
}
},
},
I have a chart with a yAxis, that has a minimum of -5, and max of 5.
The yAxis has these labels: -5, -2.5, 0, 2.5, 5.
My config is so close - I have the right amount of grid/plot lines, but I want to hide a couple of the text labels in the yAxis (not the actual lines relating to the label).
In other words, I want to remove or hide the -2.5 and 2.5 labels.
I've tried various methods in the yAxis, eg step, but it's not achieving what I want.
yAxis: {
labels: {
step: 5
}
}
JSFiddle
Any ideas how to achieve this?
I nearly didn't post this question because I found a (non-SO) answer - perhaps this will help others.
I don't know if this is the most elegant approach for highcharts, but you can use the label formatter to achieve this.
In my case, instead of this:
labels: {
formatter: function () {
return this.value+'%';
}
}
We can add a conditional to check the label's value, and only return something if it's what we want. All together:
yAxis: {
//...
labels: {
formatter: function () {
if (this.value !== -2.5 && this.value !== 2.5) {
return this.value+'%';
}
},
step: 1
},
//...
},
Example
Warning: hard coding some values and depending on them in this way is risky if you have dynamic data. For this instance we don't have dynamic data, they will be fixed, so it's safe for us. Another approach could be to iterate over each value/label and only return every X child as you require.
I have a grid with 4 doughtnut charts on each column for different periods of time: last 90 days, last 60 days, last 7 days and today.
The problem with today is that it doesn't always show data, especially in the morning. Is there a way to force ChartJS to show the chart even if it doesn't have any data?
Here's an example: http://jsfiddle.net/6xV78/219/
var pieData = [
{
value: 0,
color:"#3F9F3F"
},
{
value : 0,
color : "#222"
}
];
I found a quick work-around, not sure how "good" or "valid" way it is but it's working for me. If the values are null/zero I replaced them with -1 to retain the looks of the chart and then use the custom tooltip function to override the output.
{
...
data: [earned == 0 ? -1 : earned, pending == 0 ? -1 : pending]
...
},
options: {
tooltip: {
callbacks: {
label: function (tooltipItem, data) {
const value = data['datasets'][0]['data'][tooltipItem['index']];
return '$' + (value == -1 ? 0 : value);
}
}
}
}
Obviously I have 2 slices and when both are 0 the chart is displayed with 2 equal halves both showing $0 income (both earned and pending).
*Do note that this will still take 1 into account when others aren't null so you need to take care of that on your end. I added a method to verify if ALL values are null and that's the only case I display it like this.
A pie chart with all values equal to zero is ill-defined. Because the angle (and the area) of each slice is proportionate to the ratio of the slice's respective value over the sum of all values. If all values are equal to zero, then their sum is zero. Division by zero should be rightfully avoided by the library (hopefully by design), resulting in the no-pie-chart case you encounter. It should be the programmer's responsibility to detect the all-zeros case before populating the chart, if such a case has a possibility of occurring. Then the programmer could either display a "No data yet. What are you doing up so early? Go to sleep." message, if all values are zero. Or, maybe, if they terribly need to keep the looks consistent (having a chart there all the time), they could show a special all-black no-data pie chart with the following dummy data:
var pieNoData = [
{
value: 1,
color: "#000000"
}
];
There is no shame in disclosing that no data exists yet, though.
I want to make a graph with Highcharts/Highstock which looks like this (sorry for the bad graphic ;)):
I already found out how to do the columns and the line. What I could not find out (or what might not be possible) is:
how to have columns and lines on both sides of the x-axis?
edit: I want to set the distance between the tick points manually and statically!
how to have a x-axis which is not only irrgular, but also only shows some points with a description?
EDIT: Here is what I came up with by now: http://jsfiddle.net/pJEER/ The only thing missing is to give the columns an individual width (isn't their anything like x: 2-4), and to color them dynamically based on their value!
Thank you very much in advance!
You can use tickPositioner
http://api.highcharts.com/highcharts#xAxis.tickPositioner and ordinal as false: http://api.highcharts.com/highstock
No a straight answer but some advices:
to make column with specific width you need to have each column in a different series
for each column you can set specific color using data: [{ x: X, y:Y, color: specific_color}]. So to set specific color based on value, preprocess your data with adding property color.
To format a column based on their value you can use a little helper function where you return the point object with a certain color based on the input value.
function scatterDot(x, y, color){
return {
"x": x
, "y": y
, "color": color
, "marker": { "fillColor": color, "states": { "hover": { "fillColor": color } } }
};
}
For the dynamic plotbands you could also use a formatter function to show it depending on if it's in a specific range, making the tickpositions flexible instead of preset. I did similar for setting the datalabels.
dataLabels: {
enabled: true,
formatter: function() {
if (this.percentage >= 0) {
return this.key +"<br />"+ this.y+" ("+Math.round(this.percentage)+"%)";
} else {
return '';
}
}
}