-
Notifications
You must be signed in to change notification settings - Fork 3
/
tide-chart.js
122 lines (112 loc) · 3.65 KB
/
tide-chart.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// I couldn't find a tide chart that I liked, so what the hell lets just build one...
class TideChart {
constructor(stationId) {
this.stationId = stationId;
// Get the tide predictions for several days, so that the edges of the graph are filled in.
var yesterday = moment().subtract(1, 'days');
var tomorrow = moment().add(1, 'days');
var tideDataUrl = "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?product=predictions&application=NOS.COOPS.TAC.WL&begin_date="
+ yesterday.format(TideChart.DATE_FORMAT)
+ "&end_date="
+ tomorrow.format(TideChart.DATE_FORMAT)
+ "&datum=MLLW&station="
+ stationId
+ "&time_zone=lst_ldt&units=english&interval=hilo&format=json";
this.xmlhttp = new XMLHttpRequest();
this.xmlhttp.onreadystatechange = this.onDataLoad.bind(this);
this.xmlhttp.open("GET", tideDataUrl, true);
this.xmlhttp.send();
}
static get FONT_SIZE() {
return 20;
}
static get DATE_FORMAT() {
return 'YYYYMMDD';
}
static get BLUE() {
return 'rgb(59, 73, 227)';
}
static get BLACK() {
return 'rgb(0, 0, 0)';
}
onDataLoad() {
if (this.xmlhttp.readyState==4) {
if (this.xmlhttp.status==200) {
var response = JSON.parse(this.xmlhttp.responseText);
var result = [];
var currentDate = moment().date();
for (var i=0; i<response.predictions.length; i++) {
var prediction = response.predictions[i];
var predictionMoment = moment(prediction.t);
result.push({x: predictionMoment, y: prediction.v});
}
this.createChart(result);
} else {
// On error, don't show a chart.
console.error("Didn't get the expected status: " + this.xmlhttp.status);
}
}
}
createChart(tidePredictions) {
var ctx = document.getElementById(this.stationId);
var config = {
type: 'line',
data: {
datasets: [{
label: 'Tide Height',
borderColor: TideChart.BLACK,
backgroundColor: TideChart.BLUE,
pointRadius: 5,
pointHoverRadius: 10,
data: tidePredictions,
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'hour'
},
ticks: {
fontSize: TideChart.FONT_SIZE,
// Only display data for current day, even though we have more data than that. The extra data isn't
// visible, it helps form the curve at the graph boundaries. And graphing a full days worth of data
// helps shows the peaks and troughs in the graph.
min: moment().startOf('day'),
max: moment().endOf('day'),
},
}],
yAxes: [{
ticks: {
// No min, since tide can go negative
fontSize: 20,
},
}],
},
legend: {
labels: {
fontSize: TideChart.FONT_SIZE
},
},
// This uses the ChartJS annotation plugin to draw a red vertical line at the current time
// The other charts are monitoring live data, and the last piece of data is most relevant.
// This chart is using predictions, so it's much easier to read with a marker.
annotation: {
drawTime: 'afterDatasetsDraw',
annotations: [
{
type: "line",
mode: "vertical",
scaleID: "x-axis-0",
value: moment(),
borderColor: "red",
borderWidth: 3,
}
]
},
},
};
new Chart(ctx, config);
}
}