397 lines
14 KiB
JavaScript
397 lines
14 KiB
JavaScript
|
define([
|
||
|
'knockout', 'jquery', 'text!./Weather2.html', 'props', 'flot', 'flotresize'
|
||
|
], function(ko, jquery, htmlString, SGPropertyNode) {
|
||
|
|
||
|
function ViewModel(params, componentInfo) {
|
||
|
// componentInfo.element
|
||
|
|
||
|
var self = this;
|
||
|
|
||
|
function createIsotherms() {
|
||
|
var reply = [];
|
||
|
for (x = -50; x < 50; x += 10) {
|
||
|
reply.push([
|
||
|
x, -0.02
|
||
|
]);
|
||
|
reply.push([
|
||
|
x, 16
|
||
|
]);
|
||
|
reply.push(null);
|
||
|
}
|
||
|
/*
|
||
|
* for (x = -160; x < 50; x += 10) { reply.push([ x, -56 ]);
|
||
|
* reply.push([ x + 116, 50 ]); reply.push(null); }
|
||
|
*/
|
||
|
return reply;
|
||
|
}
|
||
|
|
||
|
function createDryAdiabates() {
|
||
|
var reply = [];
|
||
|
/*
|
||
|
* for (x = -35; x <= 200; x += 20) { reply.push([ x, 1050 ]);
|
||
|
* reply.push([ x-160, 100 ]); reply.push(null); }
|
||
|
*/
|
||
|
return reply;
|
||
|
}
|
||
|
|
||
|
function createClouds() {
|
||
|
var reply = [];
|
||
|
|
||
|
reply.push([
|
||
|
-50, 0.3, 0.
|
||
|
]);
|
||
|
reply.push([
|
||
|
-30, 3.0, 1.8
|
||
|
]);
|
||
|
reply.push([
|
||
|
-10, 5.0, 4
|
||
|
]);
|
||
|
reply.push([
|
||
|
10, 7.5, 4
|
||
|
]);
|
||
|
reply.push([
|
||
|
30, 12, 11.5
|
||
|
]);
|
||
|
return reply;
|
||
|
}
|
||
|
|
||
|
jquery.get('/json/environment/config?d=4', null, function(data) {
|
||
|
var wx = new SGPropertyNode(data);
|
||
|
|
||
|
function createProbes(k) {
|
||
|
var probes = [];
|
||
|
wx.getNode("boundary").getChildren("entry").forEach(function(entry) {
|
||
|
probes.push([
|
||
|
entry.getValue(k, 15), entry.getValue("elevation-ft", 0) * 0.3048 / 1000
|
||
|
// km
|
||
|
]);
|
||
|
});
|
||
|
wx.getNode("aloft").getChildren("entry").forEach(function(entry) {
|
||
|
probes.push([
|
||
|
entry.getValue(k, 15), entry.getValue("elevation-ft", 0) * 0.3048 / 1000
|
||
|
// km
|
||
|
]);
|
||
|
});
|
||
|
return probes;
|
||
|
}
|
||
|
|
||
|
function createWind() {
|
||
|
var wind = [];
|
||
|
wx.getNode("boundary").getChildren("entry").forEach(function(entry) {
|
||
|
wind.push([
|
||
|
entry.getValue("wind-speed-kt", 0), entry.getValue("elevation-ft", 0) * 0.3048 / 1000, // km
|
||
|
entry.getValue("wind-from-heading-deg", 0),
|
||
|
]);
|
||
|
});
|
||
|
wx.getNode("aloft").getChildren("entry").forEach(function(entry) {
|
||
|
wind.push([
|
||
|
entry.getValue("wind-speed-kt", 0), entry.getValue("elevation-ft", 0) * 0.3048 / 1000, // km
|
||
|
entry.getValue("wind-from-heading-deg", 0),
|
||
|
]);
|
||
|
});
|
||
|
return wind;
|
||
|
}
|
||
|
|
||
|
self.wxData()[3].data = createProbes("temperature-degc");
|
||
|
self.wxData()[4].data = createProbes("dewpoint-degc");
|
||
|
self.wxData()[5].data = createWind();
|
||
|
self.wxData.notifySubscribers(self.wxData.peek());
|
||
|
});
|
||
|
|
||
|
self.wxData = ko.observableArray([
|
||
|
{// Series: Isotherms
|
||
|
color : 'rgb(0, 0, 255)',
|
||
|
data : createIsotherms(),
|
||
|
label : "Isotherm",
|
||
|
lines : {
|
||
|
lineWidth : 0.5,
|
||
|
show : true
|
||
|
},
|
||
|
points : {
|
||
|
show : false
|
||
|
},
|
||
|
bars : {
|
||
|
show : false
|
||
|
},
|
||
|
shadowSize : 0,
|
||
|
yaxis : 2, // on linear scale
|
||
|
}, {// Series: Dry Adiabat
|
||
|
color : 'rgb(0, 255, 0)',
|
||
|
data : createDryAdiabates(),
|
||
|
label : "dry adiabat",
|
||
|
lines : {
|
||
|
lineWidth : 0.5,
|
||
|
show : true
|
||
|
},
|
||
|
points : {
|
||
|
show : true
|
||
|
},
|
||
|
bars : {
|
||
|
show : false
|
||
|
},
|
||
|
shadowSize : 0,
|
||
|
yaxis : 1,
|
||
|
}, { // clouds
|
||
|
color : 'rgb(128,128,128)',
|
||
|
data : createClouds(),
|
||
|
label : 'clouds',
|
||
|
lines : {
|
||
|
show : false
|
||
|
},
|
||
|
bars : {
|
||
|
show : true,
|
||
|
lineWidth : 0,
|
||
|
barWidth : 20,
|
||
|
fillColor : {
|
||
|
colors : [
|
||
|
{
|
||
|
opacity : 0.2
|
||
|
}, {
|
||
|
opacity : 0.9
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
shadowSize : 2,
|
||
|
yaxis : 2,
|
||
|
}, { // Temperature
|
||
|
color : 'rgb(255, 0, 0)',
|
||
|
data : [],
|
||
|
label : "temperature",
|
||
|
lines : {
|
||
|
lineWidth : 2,
|
||
|
show : true
|
||
|
},
|
||
|
points : {
|
||
|
show : true
|
||
|
},
|
||
|
bars : {
|
||
|
show : false
|
||
|
},
|
||
|
shadowSize : 0,
|
||
|
yaxis : 2,
|
||
|
}, { // dewpoint
|
||
|
color : 'rgb(0, 255, 0)',
|
||
|
data : [],
|
||
|
label : "dewpoint",
|
||
|
lines : {
|
||
|
lineWidth : 2,
|
||
|
show : true
|
||
|
},
|
||
|
points : {
|
||
|
show : true
|
||
|
},
|
||
|
bars : {
|
||
|
show : false
|
||
|
},
|
||
|
shadowSize : 0,
|
||
|
yaxis : 2,
|
||
|
}, {
|
||
|
color : 'rgb(0, 255, 0)',
|
||
|
data : [],
|
||
|
label : "windarrows",
|
||
|
lines : {
|
||
|
show : false
|
||
|
},
|
||
|
points : {
|
||
|
show : false
|
||
|
},
|
||
|
bars : {
|
||
|
show : false
|
||
|
},
|
||
|
windarrows : {
|
||
|
show : true,
|
||
|
},
|
||
|
shadowSize : 0,
|
||
|
yaxis : 2,
|
||
|
|
||
|
}
|
||
|
]);
|
||
|
|
||
|
self.wxOptions = {
|
||
|
legend : {
|
||
|
show : false,
|
||
|
},
|
||
|
xaxis : {
|
||
|
show : true,
|
||
|
position : "bottom",
|
||
|
color : 'blue',
|
||
|
tickColor : 'green',
|
||
|
min : -56,
|
||
|
max : 50,
|
||
|
tickLength : 0,
|
||
|
},
|
||
|
yaxes : [
|
||
|
{ // Axis 1: Pressure (hpa), Log-P
|
||
|
show : true,
|
||
|
position : "left",
|
||
|
color : 'blue',
|
||
|
tickColor : 'blue',
|
||
|
min : 100,
|
||
|
max : 1050,
|
||
|
// tickLength : 0,
|
||
|
transform : function(v) {
|
||
|
return -Math.log(v);
|
||
|
},
|
||
|
inverseTransform : function(v) {
|
||
|
return Math.exp(-v);
|
||
|
},
|
||
|
|
||
|
}, { // Axis 2: Altitude (km)
|
||
|
show : true,
|
||
|
position : "right",
|
||
|
color : 'black',
|
||
|
tickColor : 'green',
|
||
|
min : -.020,
|
||
|
max : 16,
|
||
|
tickLength : 0,
|
||
|
}
|
||
|
],
|
||
|
|
||
|
grid : {
|
||
|
hoverable : true,
|
||
|
clickable : true
|
||
|
},
|
||
|
|
||
|
hooks : {
|
||
|
processRawData : function(plot, series, data, datapoints) {
|
||
|
if (series.windarrows && series.windarrows.show) {
|
||
|
datapoints.format = [
|
||
|
{
|
||
|
x : true,
|
||
|
number : true,
|
||
|
required : true
|
||
|
|
||
|
}, {
|
||
|
y : true,
|
||
|
number : true,
|
||
|
required : true
|
||
|
|
||
|
}, {
|
||
|
number : true,
|
||
|
required : true
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
drawSeries : function(plot, ctx, series) {
|
||
|
if (series.windarrows && series.windarrows.show) {
|
||
|
function drawSeriesWindarrows(datapoints) {
|
||
|
var points = datapoints.points, ps = datapoints.pointsize;
|
||
|
for (var i = 0; i < points.length; i += ps) {
|
||
|
var ws = points[i], y = points[i+1], wd = points[i+2];
|
||
|
|
||
|
var x = series.xaxis.p2c(40);
|
||
|
y = series.yaxis.p2c(y);
|
||
|
|
||
|
ctx.save();
|
||
|
ctx.translate(x,y);
|
||
|
ctx.rotate((wd+180) * Math.PI/180);
|
||
|
|
||
|
ctx.beginPath();
|
||
|
ctx.arc(0,0, 3, 0, Math.PI * 2, false);
|
||
|
ctx.closePath();
|
||
|
|
||
|
ctx.moveTo(0,0);
|
||
|
ctx.lineTo(0,9*5);
|
||
|
var pos = 0;
|
||
|
while( ws >= 5 ) {
|
||
|
if( ws >= 50 ) {
|
||
|
ws -= 50;
|
||
|
ctx.moveTo(0,(9-pos)*5);
|
||
|
ctx.lineTo(-10,(8.5-pos)*5);
|
||
|
ctx.lineTo(0,(8-pos)*5);
|
||
|
pos++;
|
||
|
} else if( ws >= 10 ) {
|
||
|
if( pos > 0 ) pos++;
|
||
|
ws -= 10;
|
||
|
ctx.moveTo(0,(9-pos)*5);
|
||
|
ctx.lineTo(-10,(9.5-pos)*5);
|
||
|
} else {
|
||
|
pos++;
|
||
|
ws -= 5;
|
||
|
ctx.moveTo(0,(9-pos)*5);
|
||
|
ctx.lineTo(-5,(9.25-pos)*5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ctx.stroke();
|
||
|
ctx.restore();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
var plotOffset = plot.getPlotOffset();
|
||
|
|
||
|
ctx.save();
|
||
|
ctx.translate(plotOffset.left, plotOffset.top);
|
||
|
ctx.lineWidth = 1.5;
|
||
|
ctx.strokeStyle = 'black';
|
||
|
|
||
|
drawSeriesWindarrows(series.datapoints);
|
||
|
|
||
|
ctx.restore();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
};
|
||
|
|
||
|
self.afterUpdate = function(element) {
|
||
|
var yaxisLabel = jquery("<div class='axisLabel yaxisLabel'></div>").text("Pressure (hpa)").appendTo(element);
|
||
|
|
||
|
// Since CSS transforms use the top-left corner of the label as the
|
||
|
// transform origin,
|
||
|
// we need to center the y-axis label by shifting it down by half
|
||
|
// its
|
||
|
// width.
|
||
|
// Subtract 20 to factor the chart's bottom margin into the
|
||
|
// centering.
|
||
|
|
||
|
yaxisLabel.css("margin-top", yaxisLabel.width() / 2 - 20);
|
||
|
}
|
||
|
|
||
|
var highlighted = null;
|
||
|
|
||
|
self.plotHover = function(pos, item) {
|
||
|
|
||
|
if (highlighted) {
|
||
|
self.wxData()[highlighted.seriesIndex].data[highlighted.dataIndex] = [
|
||
|
pos.x1, highlighted.datapoint[1]
|
||
|
];
|
||
|
this.setData(self.wxData());
|
||
|
this.draw();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self.plotClick = function(pos, item) {
|
||
|
if (highlighted) {
|
||
|
this.unhighlight(highlighted.series, highlighted.datapoint);
|
||
|
highlighted = null;
|
||
|
} else {
|
||
|
if (item && item.seriesIndex != 3 && item.seriesIndex != 4)
|
||
|
return;
|
||
|
|
||
|
highlighted = item;
|
||
|
if (highlighted)
|
||
|
this.highlight(highlighted.series, highlighted.datapoint);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ViewModel.prototype.dispose = function() {
|
||
|
}
|
||
|
|
||
|
// Return component definition
|
||
|
return {
|
||
|
viewModel : {
|
||
|
createViewModel : function(params, componentInfo) {
|
||
|
return new ViewModel(params, componentInfo);
|
||
|
},
|
||
|
},
|
||
|
template : htmlString
|
||
|
};
|
||
|
});
|