I have to make a series as shown in the image.
The Dates and the values are dynamically generating based on the user selection. The Time is in 24 hrs format. Please tell me how can i create the series for this. Also how to put the duration 1 hour for the time value.
Image for Reference:
In your series data you are using data: [Date.UTC(2012, 10, 01, 12,11,10)] you can simply change that to: data: [90 *60 * 1000] //For 90 Minute
Here is the LIVE DEMO
If you want to plot other series for other days then you should add categories in xAxies. for example for showing 3 days:
xAxis: {
categories: ['01/10/2012', '01/11/2012', '01/2/2012']
},
And in series-data use equal number of parameters as you have in your categories for 3 categories:
data: [ 50 *60 * 1000, 100 *60 * 1000, 50 *60 * 1000 ]
See the LIVE DEMO
Use formatter in tooltip to see a correct hour:minutes when you hover the series.
tooltip: {
formatter: function() {
var ms = this.y;
var x = ms / 1000;
var seconds = x % 60;
x = x / 60;
var minutes = x % 60;
x = x / 60;
var hours = parseInt(x % 24);
x = (x / 24);
var days = parseInt(x);
if(days == 0)
{
return '<b>' + this.series.name +'</b> ->' + this.x + '<br/>' + hours +':' + minutes;
} else {
return '<b>' + this.series.name +'</b><br/>' + days + ' Day ' + hours +':' + minutes;
}
}
},
See the LIVE DEMO
Related
I have a chart with 3 X axes, the first show the year, the next line shows the Quarter (3 months) and the third by month, the expected behavior is similar to the following:
Now I do understand that because of the space, some of them disappear, but I tried to use allowOverlap and nothing happnes, rotate 90 or -90 and also nothing happens, and the worst of all is... when I zoom it shows correctly, but if I zoom out then zoom in other part of the chart, most of the months don't show, not because of lack of space, not sure why?, please take a look:
and when zooming out... (at the beginning it was showing just some months because of space, how did this get the space now?)
and when zooming back in...
please take a look at my code below:
xAxis: [
{
tickInterval: 1000 * 60 * 60 * 24 * 30,
labels: {
allowOverlap: true,
format: '{value:%b}',
style: {
fontSize: '8px'
},
rotate: 90,
},
units: [
[
'month',
[1]
]
]
},
{
currentDateIndicator: {
width: 1,
dashStyle: 'dash',
color: 'red',
label: undefined,
},
tickInterval: 1000 * 60 * 60 * 24 * 30,
units: [[
'month',
[3]
],],
labels: {
align: "center",
allowOverlap: true,
formatter: function AxisLabelsFormatterCallbackFunction() {
var providedLocalDate = new Date(this.value);
var realDate = new Date(providedLocalDate.getTime() + (providedLocalDate.getTimezoneOffset() * 60 * 1000));
var month = realDate.getMonth();
var QuarterNumber;
var MonthInits = [];
if (month >= 0 && month <= 2) {
QuarterNumber = 1;
MonthInits[0] = 'J';
MonthInits[1] = 'F';
MonthInits[2] = 'M';
}
if (month >= 3 && month <= 5) {
QuarterNumber = 2;
MonthInits[0] = 'A';
MonthInits[1] = 'M';
MonthInits[2] = 'J';
}
if (month >= 6 && month <= 8) {
QuarterNumber = 3;
MonthInits[0] = 'J';
MonthInits[1] = 'A';
MonthInits[2] = 'S';
}
if (month >= 9 && month <= 11) {
QuarterNumber = 4;
MonthInits[0] = 'O';
MonthInits[1] = 'N';
MonthInits[2] = 'D';
}
return `<div style="font-size: x-small; font-family:arial;font-weight:bold; color:${((QuarterNumber == 1 | QuarterNumber == 3) ? "#B86B00;" : "#0068B5;")};">QTR ${QuarterNumber}</div>`;
},
},
},
{
tickInterval: 1000 * 60 * 60 * 24 * 365, // Year
labels: {
format: '{value:%Y}',
style: {
fontSize: '15px'
}
},
},
],
I'm trying to use your gantt chart library to create something with milestones as follow:
I would like to have Quarter 1 / 20XX, Quarter 2 / 20XX etc... instead of these 1 2 3 4 5 6... numbers on top, I been inspecting and trying almost anything and I think I need you help, as I could not figure it out. I did try using tickInterval and tickAmount on the xAxis but it seems to do whatever it wants and I'm a little frustrated now... please provide me with any help, thank you forehand.
This is how I did it, I hope this helps anybody like me, going crazy without examples :-( (simplified for space reasons)
xAxis: [{
...
title: { text: 'Quarters' },
units: [
['month', [3]],
],
useHTML: true,
labels: {
align: "center",
format: '{value: %b-%y}',
formatter: function AxisLabelsFormatterCallbackFunction() {
var providedLocalDate = new Date(this.value);
var realDate = new Date(providedLocalDate.getTime() + (providedLocalDate.getTimezoneOffset() * 60 * 1000));
var month = realDate.getMonth();
var QuarterNumber;
if (month >= 0 && month <= 2)QuarterNumber = 1;
if (month >= 3 && month <= 5) QuarterNumber = 2;
if (month >= 6 && month <= 8) QuarterNumber = 3;
if (month >= 9 && month <= 11) QuarterNumber = 4;
var year = realDate.getFullYear().toString();
var year2digits = year.substring(year.length - 2, year.length);
return 'Q' + QuarterNumber + '-<span class="font-weight-bold">' + year2digits + '</span>';
},
},
Use xAxis.labels.format(xAxis.labels.formatter as well) or xAxis.dateTimeLabelFormats to format labels depending on provided data:
Example:
xAxis: [{
labels: {
format: 'Month: {value: %m}'
}
}],
API Reference:
https://api.highcharts.com/gantt/xAxis.dateTimeLabelFormats
https://api.highcharts.com/gantt/xAxis.labels.format
Demo:
https://jsfiddle.net/BlackLabel/5hopuL8f/
I have Highcharts chart rendered on yAxis[0] and whenever the user selects an indicator like Aroon Oscillator, MACD etc. it is added as a new yAxis in the rendering container. Example:
The above snapshot is with the Aroon Oscillator. All good.
When i select Slow Stochastic though i get the following:
First of all both SS$K and SS$D have the same value as you can see in the tooltip which is clearly wrong and both lines have the same color for a reason when they should not because:
I tried to log the p.series.yData[p.point.index] (the currently hovered point yData value) in my console and for my surprise I get the following:
It returns an array (but why) of 2 values, and both plots access the first value, instead of SS%D accessing the second value. This is a Slow Stochastic problem from Highcharts since the Aroon Oscillator which has the same philosophy of many plots on the same yAxis, still works fine as you can see in the first picture (where the lines have the correct color and correct values assigned).
Lastly as you can see with another indicators MACD (which has the same issue as mentioned before with Slow Stochastic) - and VPT which works as intended, when i go full range, those have a gap at start. Why is that happening?
Has anyone come across a similar indicator problem from Highcharts and if so, could anyone give me his/her lights on how to solve the problem?
Thanks in advance, Christopher.
P.S. Those are my tooltip options for highcharts:
tooltip: {
formatter: function() {
let finalDate = '';
let tooltipString = '';
$.each(this.points, function(i, p) {
// console.log(p.series.name, p.series.yData[p.point.index]);
//Starting date
let dateTo = new Date(p.x),
month = '' + (dateTo.getMonth() + 1),
day = '' + dateTo.getDate(),
year = dateTo.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
let intradayTime = '';
if (p.point.isIntradayData) {
let hours = dateTo.getHours();
let minutes = ('0' + dateTo.getMinutes()).slice(-2);
intradayTime += ' ' + hours + ':' + minutes;
}
dateTo = [day, month, year].join('.');
//If we wanna display previous date too:
let dateFrom = '';
if (p.point.previousDate) {
dateFrom = new Date(p.point.previousDate);
month = '' + (dateFrom.getMonth() + 1);
day = '' + dateFrom.getDate();
year = dateFrom.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
dateFrom = [day, month, year].join('.');
dateFrom += ' - ';
}
finalDate = dateFrom + dateTo + intradayTime;
if (p.series.userOptions.compare == 'percent') {
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
' ' +
p.point.percentageDifference +
`%(${p.y})`;
('</span>');
} else if (
p.series.type == 'candlestick' ||
p.series.type == 'ohlc'
) {
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Open: ' +
p.point.open +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'High: ' +
p.point.high +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Low: ' +
p.point.low +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Close: ' +
p.point.close +
'</span> <br>';
} else {
let pointValueFormatted = p.y.toFixed(2);
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
' ' +
pointValueFormatted +
'</span>';
}
});
return (
'<span style=" font-size:10px; font-family:\'Arial\'">' +
finalDate +
'</span>' +
tooltipString
);
},
borderColor: '#7fb7f0',
shared: true,
},
INDICATORS LOGIC
It's impossible to reproduce it in jsfiddle due to the size, the complexity and for security reasons due to policies. So a user can select indicators from a tabmenu like:
and they way the indicators are sorted:
//Sorting indicators.
sortIndicators() {
console.log(`Function Call: sortIndicators()`);
this.cleanIndicators(); // Just clearing the chart yaxises and the indicators array list to iterate over indicators again.
let counter = 0;
//For every indicator
for (let indicator of this.indicators) {
//If it is chart indicator we render it on yAxis[0] with our prices
if (toolsManager.isChartIndicator(indicator)) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
if (indicator.arrayOfObj) {
for (let arg of indicator.arrayOfObj) {
this.highchartOptions.series.push(arg);
}
} else {
this.highchartOptions.series.push(indicator);
}
} else {
//If it not chart indicator
this.highchartOptions.chart.height +=
2 * this.yAxisMargin + this.yAxisHeight;
let topCalculation =
456 + (counter + 1) * this.yAxisMargin + counter * this.yAxisHeight;
//yAxis to add
let addedAxis = {
title: {
enabled: false,
},
opposite: true,
min: null,
height: this.yAxisHeight,
top: topCalculation + this.yAxisMargin,
showLastLabel: false,
labels: {
enabled: true,
x: -30,
y: 0,
style: {
fontSize: '10px',
fontFamily: 'Arial',
color: '#999999',
},
},
};
this.highchartOptions.yAxis.push(addedAxis);
if (indicator.arrayOfObj) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
for (let arg of indicator.arrayOfObj) {
//for every array of that arrayOfObj
arg.yAxis = counter + 1;
this.highchartOptions.series.push(arg); //push it to series
}
} else {
indicator.yAxis = counter + 1;
if (indicator.id === 'volume') {
indicator.data = this.volumeSeries;
}
this.highchartOptions.series.push(indicator);
}
counter++;
}
}
},
the part where the magic happens is here:
if (indicator.arrayOfObj) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
for (let arg of indicator.arrayOfObj) {
//for every array of that arrayOfObj
arg.yAxis = counter + 1;
this.highchartOptions.series.push(arg); //push it to series
}
} else {
indicator.yAxis = counter + 1;
if (indicator.id === 'volume') {
indicator.data = this.volumeSeries;
}
the reason it is implemented like this is because when an indicator is selected an object is returned from the server which may have one of the two following structures:
data structure 1:
data structure 2:
And after sorting out what type of structure I am dealing with, I am pushing it into the series to display. counter variable is just used for the y-axis's. Arron Oscillator and Slow Stochastic both fulfill the first part of the conditional, because both return an object which contains and arrayOfObj (for the line colors etc as you can see in the photo uploaded).
I have created a spline real time chart where I want to show points at regular intervals.
Every point is an event taking place after one minute. However I am having a hard time trying to understand all the moving pieces:
the interval function on the highchart demo I referred updated every 1 second, I have made that 6000.
the dummy updating in the javascript just takes the latest time and appends it, is there supposed to be some delay introduced there?
the dummy initialization data in series has a for loop which again I could not understand. I understand that javascript produces a UNIX timestamp and its millisecond manipulation however the default code (again slightly modified from a highchart demo) runs from -9999 to 0 and multiples by a number.
I want to understand these parts and make sure that every time my x axis 'ticks' towards the right, I have a one minute gap and only one point on the graph.
PS: Please forgive any missing brackets, they might have been missed while posting the question, but I assure you that it isnt a problem.
Here is my code for series:
series: [{
type: 'spline',
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -9999; i <= 0; i += 1) {
data.push([
time + i * 60000,
Math.round(Math.random() * 100) + 10
]);
}
return data;
}())
}]
Here is my code for the chart:
chart: {
events: {
load: function () {
// Set up the updating
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100) + 10
series.addPoint([x, y], true, true);
}, 6000);
}
}
}
As to your questions:
If you want to have 1 minute data interval, you need to use 60000 value (60 * 1000), 6000 milliseconds is 6 seconds.
Current date in the interval function is taking every 6000 milliseconds, which causes gaps in the data every 6000 milliseconds.
That data initialization depends on subtracting multiples of six seconds from the current timestamp:
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -9999; i <= 0; i += 1) {
if (i === -500) {
console.log(time, i, 60000); // 1560941909847 + (-500 * 60000)
console.log(time + i * 60000); // 1560911909847
} else if (i === -499) {
console.log(time, i, 60000); // 1560941909847 + (-499 * 60000)
console.log(time + i * 60000); // 1560911969847
} else if (i === 0) {
console.log(time, i, 60000); // 1560941909847 + (0 * 60000)
console.log(time + i * 60000); // 1560941909847 = actual time
}
data.push([
time + i * 60000,
Math.round(Math.random() * 100) + 10
]);
}
return data;
}())
This question already has an answer here:
How to get next point in Highcharts tooltip
(1 answer)
Closed 7 years ago.
I have a line chart with cumulative values. What I try to do in tooltip: show value of ( current point.y - previous point.y ). But I don't
know how to get the y value of the previous point in a tooltip formatter function.
You need to use loop over each point in current serie and compare current point with loop point. If are the same, then extract point with index-1 from array of points.
tooltip: {
formatter: function () {
var x = this.point.x,
y = this.y,
series = this.series,
each = Highcharts.each,
txt = 'The value for <b>' + this.x +
'</b> is <b>' + this.y + '</b>';
each(series.data, function(p, i){
if(p.x === x && series.data[i-1]) {
txt += ' Previous: ' + series.data[i-1].y;
}
});
return txt;
}
},
Example: http://jsfiddle.net/3qw6ry06/