I have a spiderweb graph with just the one data series. In the interests of printing I'd like to incorporate the value plotted in the label after the actual label name but I can't seem to work out how to do so.
This example to help explain what I mean is a bar-graph that I found in my search. The code layout is similar and a lot less cluttered than mine and I'm fairly sure a solution on this one would be easily transferable.
labels: {
formatter: function() {
return this.value + ' XX.X';
}
}
JSFiddle Here
So for the X axis I'm trying to replace the "XX.X" with the relevant Y value to get the labels: "Foo 29.9 | Bar 71.5 | Foobar 106.4"
I dug through "this" in the xAxis labels formatter and got as far as finding the Y figures at "this.chart.series[0].yData", but couldn't work out a way to associate these back to each relevant X label, and I thought it seemed the wrong way of going about things anyway.
You can do this after rendering of the chart in the chart.events.load method using setCategories. This code below assumes that each index element on the xAxis has a corresponding data element. If it doesn't then you would need to handle that case.
chart: {
events: {
load: function (event) {
var cats = this.xAxis[0].categories;
var theData = this.series[0].data;
var newCats = [];
for (var i = 0; i < cats.length; i++) {
newCats.push(cats[i] + ' ' + theData[i].y)
}
this.xAxis[0].setCategories(newCats);
}
}
}
Live demo.
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 am trying to create a bubble chart using the JS HighChart in Angular2+. Whenever there are more than 50 data points (bubbles), the graph breaks. There are the correct number of bubbles in the correct positions (x,y plots) with all different colors but the sizes are all the same even though the z-values are all different. (I am outputing the z-values in a tooltip and the z-values are accurate)
This function is how I am passing in data to the high-chart configuration.
setSeries() {
this.objData = []
this.Data.forEach(element => {
var x= element['xVal'];
var y = element['yVal'];
var z = element['zVal'].toFixed(0);
var name = element['seriesName'].trim();
var newData =[{
x:x,
y:y,
z:+z,
}]
// SetSeriesData is how i am creating the obj to pass into series=[] in highchart configuration
if(i<50) //If I comment this condition, the graph breaks. Right now, the graph is working properly
this.setSeriesData(sumData, name, this.objData)
i++
})
this.options.series = this.objData;
this.generateChart();
}
This is my setSeriesData function.
setSeriesData(graphData: any, dataName: any, objData: any){
var obj = {};
obj['name'] = dataName;
obj['data'] = graphData;
obj['events'] = {click: function(e) {
//takes me to another link
}};
objData.push(obj)
}
In the above function, I configured the chart so that when you click the bubble, it takes you to another page. When the data points >50, this click functionality is not working either. In addition, the fillOpacity is not correct.
Just a few things to point out
1. I am using Angular 2+
2. The discovered issues are, fillOpacity, click, and size based on z-value.
3. It works perfectly when the data points are less than 50
How can I fix this?
On a Highcharts chart with datetime axis, I am trying to highlight weeks. First, I had the idea to use the grid and to set tickInterval to 7*24*60*60*1000 and minorTickInterval to 24*60*60*1000. With the option gridLineWidth set to 2, the result is almost perfect.
The problem is when zooming: minor ticks appears but without label. I can not find how to add it. And the labels are not dynamic.
You can try this demo: https://jsfiddle.net/gdebrion/19x4nmp5/19/
First chart is the basic one. When you zoom you can see the changes in x-axis.
Second chart is mine. The weeks are visible but when zooming in until having a day display on the full width, and the only ticks visible are the minor one, without label…
Please tell me if you have an idea. Thanks!
The API does not provide a way to display labels on minor ticks.
http://www.highcharts.com/docs/chart-concepts/axes
MINOR TICKS
If the minorTickInterval option is set, minor ticks are laid out between the major ones. This includes minor tick marks, and minor grid lines, which have their own options for look and feel, but excludes labels.
Having a peek at the source code for Highcharts, I also do not see any label representation for minor ticks as there are for the major ticks (axis.labelEdge = [];) .
https://github.com/highcharts/highcharts/blob/b6bc666da00d37c5c4e3c0d7fe238b8526e583ea/js/parts/Axis.js
...
// Major ticks
axis.ticks = {};
axis.labelEdge = [];
// Minor ticks
axis.minorTicks = {};
// List of plotLines/Bands
...
UPDATE:
Here is a slightly rough solution to enable minor tick labels for highcharts:
http://jsfiddle.net/strince/deuez7gk/
The code doesn't handle overlapping labels when the zoom is far out so you'll need to zoom in a bit to see it work.
The chart code was updated with:
// Keep track of elements created.
var minorTickLabels = new Array();
...
events: {
load: function() { addMinorTickLabels(this); },
redraw: function() { addMinorTickLabels(this); }
}
...
function addMinorTickLabels(chart) {
// The elements need to be destroyed, otherwise a dictionary
// internal to highcharts will accumulate and pollute the chart.
for (var i = 0; i < minorTickLabels.length; i++) {
var textItem = minorTickLabels[i];
textItem.destroy();
}
minorTickLabels = new Array();
var axis0 = chart.xAxis[0];
var lastIndexFound = 0;
for (var tick in axis0.minorTicks) {
var el = axis0.minorTicks[tick];
// Skip double labels on major ticks.
var index = axis0.tickPositions.indexOf(el.pos, lastIndexFound);
if (index >= 0) {
listIndexFound = index;
continue;
}
var xPos = el.mark.getBBox().x;
var yPos = el.mark.getBBox().y;
var labelText = 0;
// The formatting parameters below should be passed in.
var textItem = chart.renderer.text(Highcharts.dateFormat("%d. %b", el.pos), xPos, yPos)
.css({
color: '#101010',
fontSize: '8px'
})
.attr({
rotation: -25,
zIndex: 6
});
// Add the tick label to the chart.
textItem.add();
minorTickLabels.push(textItem);
}
};
I'm using a line chart (I think) for my data, and I'm trying to have red, yellow or green dots based upon the value of the data. The problem is, I can't even change the symbols used on the graph!
I'm using data pulled from a database, so I can't simply define the data within a series[] and then define the symbol from there, it's added using the chart.addSeries() function.
I'm sorry if this is a total noob question, I'm a total noob when it comes to JavaScript and Highcharts.
EDIT: For security reasons, I can't post the code.
Answer may not be 100% accurate, but I would do something like this:
// Loop over series and populate chart data
$.each(results.series, function (i, result) {
var series = chart.get(result.id);
//I think I have to do some sort of marker: set here
$.each(result.data, function (i, point) {
var x = point.x, // OR point[0]
y = point.y; // OR point[1]
result.data[i] = {
color: y > 100 ? 'red' : 'blue',
x: x,
y: y
}
});
if (series) {
series.update(result, false);
} else {
chart.addSeries(result, false);
}
});
chart.redraw();
As you can see, here I am adding color property to the point. Right now there is simple logic (value < 100), but you can apply there anything you want to, for example function which will return correct color etc.
Note that I am extracting x and y values. How to get them depends on how your data is formatted. It can be {x: some_valueX, y: some_valueY} or [some_valueX, some_valueY] or even some_valueY only.
Important: if you have a lot of points (1000+), don't forget to increase turboThreshold or disable it.
I would like to set different properties for my labels on the xAxis (Here is my problem).
I know how to do this for dataLabels : API.
It is similar to this.
But I don't find anything to do the same thing for xAxis.labels.
Does it exist a way to do this ?
Solution :
It changes only y property of xAxis labels.
Here is a jsFiddle.
chart: {
renderTo: 'container',
type: 'column',
events: {
load: function () {
var xAxis = this.xAxis[0];
var serie = this.series[0];
for (var current_tick in xAxis.ticks) {
var tick = xAxis.ticks[current_tick];
if(serie.data[current_tick]){
if (serie.data[current_tick].y > 0) {
tick.label.attr({
y: tick.label.y + 18
});
}
}
}
}
}
}
I am not aware of a way to do that.
What I would probably do in this situation is create to x axes, one for the positive values, and one for the negative.
{{edit - although, it seems the axis offset plugin only works (at least from what I am seeing) if you have opposite: true set for the axis.
SO, you have to offset the labels on one of them. example:
http://jsfiddle.net/jlbriggs/S48eX/