hi can someone help me i want to display last seven day data in my chart it works in this chart type https://www.highcharts.com/demo/line-time-series but not working in https://www.highcharts.com/demo/areaspline
for example if today is 05/04/2019 chart will display data from 30-03-2019 to 05-04-2019 (7 days) and areaspline chart has pointStart but how to make it dynamic to display last 7 days? here is my example
$(function() {
Highcharts.setOptions({lang:{thousandsSep:","}});
$('#container').highcharts({
chart:{
type:'areaspline',
zoomType: 'x'
},
title:{
text:null,
margin:0,
floating:true,
verticalAlign:'bottom',
x:0,
y:0
},
xAxis:{
type:'datetime',
maxZoom:48*3600*1000
},
plotOptions:{
series:{
pointStart: Date.UTC(2019, 03-1, 30),
pointInterval: 24 * 3600 * 1000 // one day
}
},
yAxis:{
title:{
text:null,
},
},
credits:{
enabled:false
},
series:[{
showInLegend:false,
name:"Dollar",
data:[1,0.5,3,2,5,2.5]
});
});
You can use tickPositioner to return the 7 days positions point of last 7 days.
Point start needs to be set with the current date which you can do it by:
pointStart: Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()),
var d = new Date();
d.setDate(d.getDate() - 7);
Highcharts.chart('container', {
chart: {
type: 'areaspline',
zoomType: 'x'
},
xAxis: {
type: 'datetime',
maxZoom: 48 * 3600 * 1000,
tickInterval: 24 * 3600 * 1000,
tickPositioner: function(min, max) {
var interval = this.options.tickInterval,
ticks = [],
count = 0;
while (min < max) {
ticks.push(min);
min += interval;
count++;
}
ticks.info = {
unitName: 'day',
count: 1,
higherRanks: {},
totalRange: interval * count
}
return ticks;
}
},
series: [{
showInLegend: false,
name: "Dollar",
data: [88, 96, 97, 105, 0,84,86],
pointStart: Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()),
pointInterval: 24 * 3600 * 1000 // seven days
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
For different datatype:
var d = new Date();
d.setDate(d.getDate() - 7);
Highcharts.chart('container', {
chart: {
type: 'areaspline',
zoomType: 'x'
},
xAxis: {
type: 'datetime'
},
series: [{
showInLegend: false,
name: "Dollar",
data: [
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()),88],
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+1),89],
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+2),0],
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+3),102],
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+4),114],
[Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+5),120]],
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
API references:
https://api.highcharts.com/highcharts/xAxis.tickPositioner
https://api.highcharts.com/highcharts/series.line.pointStart
Related
I am quite new to stackoverflow, django and highcharts so I apologies for any inconvenience.
So I am currently working with displaying time and dates in highcharts when I noticed a small problem.
When looking at the chart everything looks fine like this.
But when I hover my mouse about a point on the chart it shows a different value. It looks like this
I would like so that when focusing on a point it will display as HH:MM:SS like it does on the side instead of the total amount of microseconds. What do I need to change to make it happen?
Here is the code for the chart
<script>
$(function () {
$('#container').highcharts({
chart:
{
type: 'line'
},
title:
{
text: 'Time worked by {{user_to_show}}'
},
xAxis:
{
categories: {{dates|safe}}
},
yAxis:
[{
title:
{
text: ''
},
gridLineWidth: 1,
type: 'datetime', //y-axis will be in milliseconds
dateTimeLabelFormats:
{ //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
opposite: true
}],
plotOptions:
{
series:
{
dataLabels:
{
enabled: true,
formatter: function()
{
if( this.series.index == 0 )
{
return secondsTimeSpanToHMS(this.y/1000) ;
}
else
{
return this.y;
}
}
}
}
},
series:
[{
name: 'Time',
yAxis: 0,
data: {{time|safe}}
}]
});
});
function secondsTimeSpanToHMS(s) {
var h = Math.floor(s / 3600); //Get whole hours
s -= h * 3600;
var m = Math.floor(s / 60); //Get remaining minutes
s -= m * 60;
return h + ":" + (m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s); //zero padding on minutes and seconds
}
</script>
If you would like more code, data or information please tell me.
Thanks in advance for anyone that replies.
I was able to find a solution to my problem. Had to add:
tooltip:
{
formatter: function ()
{
var text = this.x + ': ' + secondsTimeSpanToHMS(this.y/1000);
return text;
}
},
and it gave this result:
(Would mark this post as answered but stackoverflow wont let me do it until 2 days)
i added this code
scales:
{
xAxes:
[{
type: 'time',
time:
{
unit: 'month',
displayFormats: { month: 'MM' },
max: '2017-10-09 18:43:53',
min: '2017-10-02 18:43:53'
}
}]
},
to the options but it does not work. Any ideas what i'm making wrong?
FIDDLE ->
https://jsfiddle.net/o473y9pw/
Since you wish to use time for x-axis, your labels array should be an array of date/time string (labels array is correspondent to x-axis).
You would also need to set the parser property (to parse the date/time correctly), and x-axis' ticks source to data (to properly generate x-axis ticks).
UPDATE
If you only have a min and max date then, you can create a nice little plugin to populate the labels (date) array dynamically, as such :
plugins: [{
beforeInit: function(chart) {
var time = chart.options.scales.xAxes[0].time, // 'time' object reference
// difference (in days) between min and max date
timeDiff = moment(time.max).diff(moment(time.min), 'd');
// populate 'labels' array
// (create a date string for each date between min and max, inclusive)
for (i = 0; i <= timeDiff; i++) {
var _label = moment(time.min).add(i, 'd').format('YYYY-MM-DD HH:mm:ss');
chart.data.labels.push(_label);
}
}
}]
note: moment.js is used to make calculations easier.
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
( for demonstration purposes, I've changed the time unit to day )
$(document).ready(function() {
new Chart(document.getElementById("chartBox"), {
type: 'line',
data: {
datasets: [{
data: [12, 19, 3, 5, 2, 3, 32, 15],
label: "",
borderWidth: 2,
borderColor: "#3e95cd",
fill: false,
pointRadius: 0
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'YYYY-MM-DD HH:mm:ss',
unit: 'day',
displayFormats: {
day: 'ddd'
},
min: '2017-10-02 18:43:53',
max: '2017-10-09 18:43:53'
},
ticks: {
source: 'data'
}
}]
},
legend: {
display: false
},
animation: {
duration: 0,
},
hover: {
animationDuration: 0,
},
responsiveAnimationDuration: 0
},
plugins: [{
beforeInit: function(chart) {
var time = chart.options.scales.xAxes[0].time, // 'time' object reference
timeDiff = moment(time.max).diff(moment(time.min), 'd'); // difference (in days) between min and max date
// populate 'labels' array
// (create a date string for each date between min and max, inclusive)
for (i = 0; i <= timeDiff; i++) {
var _label = moment(time.min).add(i, 'd').format('YYYY-MM-DD HH:mm:ss');
chart.data.labels.push(_label);
}
}
}]
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#latest/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<canvas id="chartBox"></canvas>
The dataset should be an array of objects with properties x for time and y for value.
$(document).ready(function() {
var data = [{
x: new moment().add(-10, "months"),
y: Math.random() * 100
},
{
x: new moment().add(-8, "months"),
y: Math.random() * 100
},
{
x: new moment().add(-6, "months"),
y: Math.random() * 100
},
{
x: new moment().add(-4, "months"),
y: Math.random() * 100
},
{
x: new moment().add(-2, "months"),
y: Math.random() * 100
},
{
x: new moment().add(-0, "months"),
y: Math.random() * 100
},
];
new Chart(document.getElementById("chartBox"), {
type: 'line',
data: {
datasets: [{
data: data,
borderColor: "#3e95cd",
fill: false
}]
},
options: {
scales: {
xAxes: [{
type: 'time'
}]
},
legend: false
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.bundle.min.js"></script>
<canvas id="chartBox"></canvas>
Fiddle
If the xAxis label is in date format use this code
time:
{
format: 'MM',
unit: 'month',
displayFormats: { month: 'MM' },
max: '2017-10-09 18:43:53',
min: '2017-10-02 18:43:53'
}
If the xAxis label is as what u used numerals use
time:
{
format: 'MM',
unit: 'month',
parser:'MM',
displayFormats: { month: 'MM' },
max: '2017-10-09 18:43:53',
min: '2017-00-02 18:43:53'
}
You might want to change a few things.
Your data should include time data.
If you set scale unit to be month, your min max should be more than one month to see the actual scales.
Here's simplified working example.
https://jsfiddle.net/f2xmkkao/
In this plotly example,
The first date is on the first of January,
var trace1 = {
x: ['2000-01-01',
However, the first label shown on the graph is Jan 2.
Is there a way to force the graph to start from the 1st of January?
You have several possibilities to specify the first tick value of your x-axis.
Use tick0 together with dticks
var layout = {
xaxis: {
tick0: '2000-01-01',
dtick: 7*24*60*60*1000 // 7 days
};
or completely set the tickvals yourself
var layout = {
xaxis: {
tickvals: ['2000-01-01', '2000-01-15', '2000-01-31']
};
var trace1 = {
x: ['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04', '2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08', '2000-01-09', '2000-01-10', '2000-01-11', '2000-01-12', '2000-01-13', '2000-01-14', '2000-01-15', '2000-01-16', '2000-01-17', '2000-01-18', '2000-01-19', '2000-01-20', '2000-01-21', '2000-01-22', '2000-01-23', '2000-01-24', '2000-01-25', '2000-01-26', '2000-01-27', '2000-01-28', '2000-01-29', '2000-01-30', '2000-01-31'],
y: [4.3, 8.2, 4.1, 5.6, -3, -0.2, 0.3, 0.4, 4.1, 5, 4.6, -0.2, -8.5, -9.1, -2.7, -2.7, -17, -11.3, -5.5, -6.5, -16.9, -12, -6.1, -6.6, -7.9, -10.8, -14.8, -11, -4.4, -1.3, -1.1],
mode: 'lines',
type: 'scatter',
name: '2000'
};
var data = [trace1];
var layout = {
xaxis: {
type: 'date',
title: 'January Weather',
tick0: '2000-01-01',
dtick: 7 * 24 * 60 * 60 * 1000
},
yaxis: {
title: 'Daily Mean Temperature'
},
title:'2000 Toronto January Weather'
};
Plotly.plot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv" style="width:100%;height:400px;"></div>
I am trying to make the HighStock chart's scroll bar default to the left hand side location. Essentially, I am looking at forecast data that starts from today's date. The chart defaults to a 3 month window, and I need this window's starting location to be from today. Here is an example plot:
I need the highlighted scroll bar to default to the left. I am working with a team in India on this issue, and they told me "it's not possible, and is a HighChart's limitation". I'm not saying they are wrong, but I really feel like it can be done without too much issue. Bellow is the js that generates my specific plot (not the same as the one pictured above).
$(function () {
var now = new Date();
var utc_timestamp = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
$.ajax({
type: 'GET',
url: '/Conductivity/ForecastPlot',
data: { USGSID: Source1Id },
success: function (jsonData) {
var BestCase = new Array();
var WorstCase = new Array();
for (var i = 0 ; i < jsonData.AverageForecastData.length ; i++) {
var BestData = new Object();
var WorstData = new Object();
BestData = jsonData.AverageForecastData[i];
WorstData = jsonData.MaximumForecastData[i];
BestCase.push(BestData.cond);
WorstCase.push(WorstData.cond)
}
$('#Forecast_Source_1').empty();
$('#Forecast_Source_1').highcharts('StockChart', {
rangeSelector: {
selected: 1,
},
chart: {
type: 'spline',
zoomType: 'x',
width: 630,
height: 300
},
xAxis: {
type: 'datetime',
tickInterval: 24 * 3600 * 1000 * 21,
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Conductivity'
}
},
credits: {
enabled: false
},
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function (e) {
}
}
},
marker: {
enabled:false,
lineWidth: 1
}
}
},
legend: {
enabled: true,
layout: 'horizontal',
borderWidth: 1
},
series: [{
name: 'WorstCase',
pointInterval: 24 * 3600 * 1000,
pointStart: utc_timestamp,
data: WorstCase,
color: '#FF0000'
},{
name: 'Expected',
pointInterval: 24 * 3600 * 1000,
pointStart: utc_timestamp,
data: BestCase
}]
});
}
});
});
I've taken a quick look at the API and I don't specifically see an option for this in the "scrollbar" option, but I am thinking of creating a custom zoom function that loads the appropriate window with the From: xx/xx/xx To: xx/xx/xx boxes when a user clicks on the 1m,3m,or 6m buttons.
Edit: Partial Solution
I have a partial solution that seems to be working great. Here is what I changed:
First of all, I know that all the data in my MySQL database is always rounded to the nearest day, so I made sure that the code was rounding also:
var now = new Date();
now.setHours(now.getHours()) + Math.round(now.getMinutes());
now.setMinutes(0);
var utc_timestamp_today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
var utc_timestamp_3moFromNow = Date.UTC(now.getFullYear(), (now.getMonth() + 3), now.getDate(), 0, 0, 0, 0);
After adding this in, I simply added a "min" and "max" to my "xAxis" parameter.
xAxis: {
type: 'datetime',
tickInterval: 24 * 3600 * 1000 * 21,
min: utc_timestamp_today,
max: utc_timestamp_3moFromNow,
title: {
text: 'Date'
}
You can see the new plot below. This is the actual plots I am dealing with, and you can see how when the page first loads the scroll bar is now in the proper location:
Now my only remaining issue is that when the user goes and clicks on the 1m, 3m, 6m option the graph's window scroll bar will revert to being back at the right hand side. Does anyone know how I might solve this?
Final Working Solution:
$(function () {
var now = new Date();
now.setHours(0, 0, 0, 0);;
now.setMinutes(0);
var plus1mo = new Date();
plus1mo.setMonth((now.getMonth() + 1));
plus1mo.setHours(0, 0, 0, 0);
plus1mo.setMinutes(0);
var plus3mo = new Date();
plus3mo.setMonth((now.getMonth() + 3));
plus3mo.setHours(0, 0, 0, 0);
plus3mo.setMinutes(0);
var plus6mo = new Date();
plus6mo.setMonth((now.getMonth() + 6));
plus6mo.setHours(0, 0, 0, 0);
plus6mo.setMinutes(0);
var utc_timestamp_today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
var utc_timestamp_1moFromNow = Date.UTC(plus1mo.getFullYear(), plus1mo.getMonth(), plus1mo.getDate(), 0, 0, 0, 0);
var utc_timestamp_3moFromNow = Date.UTC(plus3mo.getFullYear(), plus3mo.getMonth(), plus3mo.getDate(), 0, 0, 0, 0);
var utc_timestamp_6moFromNow = Date.UTC(plus6mo.getFullYear(), plus6mo.getMonth(), plus6mo.getDate(), 0, 0, 0, 0);
$.ajax({
type: 'GET',
url: '/Conductivity/ForecastPlot',
data: { USGSID: Source1Id },
success: function (jsonData) {
var BestCase = new Array();
var WorstCase = new Array();
for (var i = 0 ; i < jsonData.AverageForecastData.length ; i++) {
var BestData = new Object();
var WorstData = new Object();
BestData = jsonData.AverageForecastData[i];
WorstData = jsonData.MaximumForecastData[i];
BestCase.push(BestData.cond);
WorstCase.push(WorstData.cond)
}
$('#Forecast_Source_1').empty();
$('#Forecast_Source_1').highcharts('StockChart', {
rangeSelector: {
buttons: [{
type: 'month',
count: 1,
text: '1m'
}, {
type: 'month',
count: 3,
text: '3m'
}, {
type: 'month',
count: 6,
text: '6m'
}, {
type: 'all',
text: 'All'
}],
selected: 1
},
chart: {
type: 'spline',
zoomType: 'x',
width: 630,
height: 300
},
xAxis: {
type: 'datetime',
tickInterval: 24 * 3600 * 1000 * 21,
min: utc_timestamp_today,
max: utc_timestamp_3moFromNow,
title: {
text: 'Date'
},
events: {
afterSetExtremes: function (e)
{
if(e.trigger == "rangeSelectorButton" && e.rangeSelectorButton.text == "1m") {
setTimeout(function () {
Highcharts.charts[1].xAxis[0].setExtremes(utc_timestamp_today, utc_timestamp_1moFromNow)
}, 1);
}
else if(e.trigger == "rangeSelectorButton" && e.rangeSelectorButton.text == "3m") {
setTimeout(function () {
Highcharts.charts[1].xAxis[0].setExtremes(utc_timestamp_today, utc_timestamp_3moFromNow)
}, 1);
}
else if(e.trigger == "rangeSelectorButton" && e.rangeSelectorButton.text == "6m") {
setTimeout(function () {
Highcharts.charts[1].xAxis[0].setExtremes(utc_timestamp_today, utc_timestamp_6moFromNow)
}, 1);
}
}
}
},
yAxis: {
title: {
text: 'Conductivity'
}
},
credits: {
enabled: false
},
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function (e) {
}
}
},
marker: {
enabled:false,
lineWidth: 1
}
}
},
legend: {
enabled: true,
layout: 'horizontal',
borderWidth: 1
},
series: [{
name: 'WorstCase',
pointInterval: 24 * 3600 * 1000,
pointStart: utc_timestamp_today,
data: WorstCase,
color: '#FF0000'
},{
name: 'Expected',
pointInterval: 24 * 3600 * 1000,
pointStart: utc_timestamp_today,
data: BestCase
}]
});
}
});
});
The trick was setting a "timeout" function to be called after HighCharts is doing all it's stuff. Only then do I set the min/max so that I can get the appropriate range. (By the way: It's Highcharts.charts[1] because I have 2 charts)
Set this in your xAxis
xAxis : {
events: {
setExtremes: function(e) {
if(typeof(e.rangeSelectorButton)!== 'undefined')
{ this.min= utc_timestamp_today;
this.max= utc_timestamp_3moFromNow;
}
}
}
I have a very simple highcharts js chart, which has dates on x-axis and values on y-axis. It works fine with this code:
chart = new Highcharts.Chart({
chart: {
renderTo: 'chart_container',
type: 'line',
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%e / %b'
}
},
yAxis: {
title: {
text: null
},
tickInterval: 1,
tickmarkPlacement: 'on',
min: 1,
max: 5
},
series: [{
name: 'serie_1',
pointInterval: 24 * 3600 * 1000, // one day
pointStart: Date.UTC(2011, 11, 22),
data: [
2, 3, 5, 4, null, 4, 4, 4, 4, 3, 2, 2, 1, 2, 2, null
]
}]
});
I also have an event that changes the chart's data when some action is triggered:
function reloadChart(){
$.get('/my/ajax/link/', { ajax_param: 10 },
function(data){
// HOW TO GET THIS TO WORKS??? series.pointStart is readonly
chart.series[0].pointStart = data.newPointStart;
chart.series[0].setData(data.data, true);
}
);
}
My question is: How can I update my series[0].pointStart after chart has been initialized?
I would rethink this. It would be easier to create an x,y points from your y-value series instead of using the pointStart and pointInterval options.
startDate = Date.UTC(2010, 0, 1);
createData = function(beginDate){
someData = [];
for (var i = 0; i < 11; i++){
someData.push([beginDate + (3600 * 1000 * 24 * i), Math.random() * 100]);
}
return someData;
}
....
series: [{
data: createData(startDate)
}]
Then in your function:
nextDay = function(){
startDate += 3600 * 1000 * 24;
chart.series[0].setData(createData(startDate), true);
}
Working fiddle here.
i think this is what you are looking for
chart.xAxis[0].setCategories();
see also the working jsFiddle