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/
Related
The issue is that the percentage area function does not seem to work when a datetime series is missing a datapoint for some t.
E.g. removing
{
x: new Date("2008-10-31T00:00:00.000Z"),
y: 0,
drilldown: 'my_drilldown'
}
from the series in http://jsfiddle.net/qtoas0jg/3/, giving http://jsfiddle.net/qtoas0jg/4/.
The expected/desired behaviour is that the area should fill for all times t. After going through the documentation I conclude that connectNulls:false, also using step:"left" I can achieve the desire behaviour for one series, the one holding values for all t, but then again not for the second series.
Any ideas?
EDIT:
I was not able to solve the issue using Highcharts functionality. Instead I (quite unrigiously) manipulated the series that I put in by adding value 0 for the missing t. If someone stumbles apon this issue, the following might be useful:
let asd = []
// Firstly finding which t:s that need to be added for respective series
let to_be_added = series.map(arg_a => {
return([arg_a.name,arg_a.data.reduce((acc_b,arg_b) => {
// Adding all available t:s
(asd.indexOf(arg_b.x.toString())>=0?0:asd.push(arg_b.x.toString()))
acc_b.push(arg_b.x.toString())
return acc_b
},[])])
}).map(arg_a => {
return [arg_a[0],asd.filter(arg_b => arg_a[1].indexOf(arg_b)<0)]
})
// Adding the new timestamps with y:0
to_be_added.map(arg_a => {
series.map((arg_b,ind) => {
if (arg_b.name == arg_a[0]) {
arg_a[1].reverse().map(arg_c => {
series[ind].data.unshift({x:new Date(arg_c),y:0})
})
}
})
})
This problem is caused by Highcharts bug: https://github.com/highcharts/highcharts/issues/5634
To workaround use timestamps instead of Date object:
data: [{
x: new Date("2008-10-31T00:00:00.000Z").getTime(),
...
}, ...]
Live demo: http://jsfiddle.net/BlackLabel/0wr3kvt1/
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];
}
},
},
OK, I am totally baffled here. I had this working but have done something to break dygraphs. I am using dygraphs in multiple places - in some instances, I am graphing data that is not a function of time and some data that is a function of time. In the case where data is not a function of time, the x-axis is properly displayed.
In the case where the data is plotted as a function of time, (i.e. the first entry of every array is a javascript Date object) the x-axis is totally neglected (i.e. there are no labels for the x-axis). Currently, the options object looks like
vm.options = {
ylabel: 'P (mb)',
labels: ['t', 'Alicat0'],
legend: 'always',
axes: {
y: {
axisLabelWidth: 70
},
x: {
drawAxis: true,
axisLabelFormatter: function (d) {
return Dygraph.zeropad(d.getHours()) + ":" +
Dygraph.zeropad(d.getMinutes()) + ":" +
Dygraph.zeropad(d.getSeconds());
}
}
},
xlabel: "time"
};
Any help is appreciated.
Problem resolved. Turns out that my array was backwards such that my largest value (most current time) was in the 0 position of the array. Dygraphs did not like this.
I have an array of data points that I am passing to a Highcharts chart that looks like
mydata = [{
x: 1,
y: 3,
nameList: ["name1", "name2"]
}, {
x: 2,
y: 4,
nameList: ["name3", "name4"]
}]
I build the chart like this:
$("#chart").highcharts("StockChart", {
series: [{
data: mydata
}, {
data: yourdata
}]
});
Now, I would like to be able to access the nameList array from the shared tooltip, which I'm trying to do as follows:
tooltip: {
formatter: function() {
var s = "";
$.each(this.points, function(i, point) {
s += point.point.nameList;
});
return s;
},
shared: true
}
but when examining the point objects in Firebug using console.log(point), I can't seem to find the nameList entry anywhere in them. How could I access this auxiliary information in a shared series tooltip? All help is appreciated.
Eureka!
By default, Highcharts will accept several different types of input for the data of a series, including
An array of numerical values. In this case, the numberical values will be interpreted
and y values, and x values will be automatically calculated, either starting at 0 and
incrementing by 1, or from pointStart and pointInterval given in the plotOptions.
An array of arrays with two values. In this case, the first value is the x value and the
second is the y value. If the first value is a string, it is applied as the name of the
point, and the x value is incremented following the above rules.
An array of objects with named values. In this case the objects are point configuration
objects as seen below.
However, the treatment of type 3 is different from types 1 and 2: if the array is greater than the turboThreshold setting, then arrays of type 3 won't be rendered. Hence, to fix my problem, I just needed to raise the turboThreshold setting like so:
...
plotOptions: {
line: {
turboThreshold: longestArray.length + 1
}
},
...
and the chart renders the longestArray data properly. Hurray! The only drawback is that there is a considerable time spent rendering the data for much longer arrays due to "expensive data checking and indexing in long series." If any of you know how I might be able to bypass this checking or otherwise be able to speed up the processing of this data, I'd be extremely thankful if you'd let me know how.
I can see it here:
tooltip: {
formatter: function() {
var s = "";
console.log(this.points[0].point.nameList); // ["name1", "name2"]
$.each(this.points, function(i, point) {
s += point.point.nameList;
});
return s;
},
shared: true
}
I'm writing Ext JS 4 line chart component. It works all fine, but when I display labels under axis they are just too dense. I won't the number of visible labels to decrease. How to do that? Here's my code for the axis:
{
type: 'Category',
position: 'bottom',
fields: ['date'],
grid: true,
label: {
field: 'label',
rotate: { degrees:315 },
renderer: function(item) {
var date = new Date(item);
/* parseIntToStringWithZeros is a custom method somewhere else */
var day = parseIntToStringWithZeros(date.getDate());
var month = parseIntToStringWithZeros(date.getMonth());
result = day + '-' + month;
return result;
}
}
}
I think you might need to use a "Numeric" axis instead of a "Category" axis a start (not sure what your data looks like, but you might need to convert times to values to get it to work).
With the numeric axis you are supposed to be able to set the number of major tick values (where the grid lines and labels appear), by setting the steps property in the axis config; however this doesn't always work. A more surefire way is to override the applyData function which isn't documented so you need to search through the dev code to see what it's doing.
Also, to simply not render a particular label you can just return the empty string in the label renderer function. e.g. if you only want an individual "month" to show up once in the above code you could do something like this..
label: {
....
renderer: (function(){
var lastRenderedMonth = '';
return function(item){
... //your code above without the return..
if(month == lastRenderedMonth)
return "";
lastRenderedMonth = month;
return result;
};
})(),
...