How can I dynamically update pointStart series attribute from highcharts.js? - javascript

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

Related

How to display last 7 days data

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

Highcharts stream graph - how to make 1:1 scale by Y axis?

Here is my code - https://jsfiddle.net/rxqpt8u4/1/
var colors = Highcharts.getOptions().colors;
Highcharts.chart('container', {
chart: {
type: 'streamgraph',
marginBottom: 30,
zoomType: 'x'
},
yAxis: {
min:0
},
// Data parsed with olympic-medals.node.js
series: [
{
"name": "Austria",
"data": [
2, 3, 4, 5, 5, 6, 6, 6, 7
]
}]
});
Can't understand why values dont scales 1:1.
Instead of that, they scale 0.5:1.
Please advise.
The axes adapt to the data and they are independent of each other. To have the same scale on the axes set the same tickInterval, max and min properties:
events: {
load: function() {
var xAxis = this.xAxis[0];
this.yAxis[0].update({
tickInterval: xAxis.tickInterval,
max: xAxis.dataMax
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/289jtzp1/

Chart JS - Use time for xAxes

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/

Plotly - starting X axis from first data point

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>

How to make HighStock / HighChart scroll bar location default to the left hand side?

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;
}
}
}

Categories