OpenWeatherMap has a nice API that allows you to consume live weather data. I have made other simple examples here (v2.1) and here (v2.0 – doesn’t work), but you should check out the OWM API documentation and examples for more.

This example (v2.5) collects weather info from several stations across British Columbia and Alberta, interpolates temperature values between the stations using the Inverse Distance Weighting method, and displays both the stations (points) and interpolated surface (raster) as PaperJS objects.

<!DOCTYPE html>
<html>
<head>
<!---------------------
Code by Darren Wiens
dkwiens@gmail.com
----------------------->
<style type="text/css">
html { height: 100% }
#map { height: 500px; width: 500px; }
canvas { position: absolute; top: 10; left: 10; z-index: 1; pointer-events:none; }
</style>
<!-- Load the Paper.js library -->
<script type="text/javascript" src="http://darrenwiens.net/scripts/paper.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<!-- Define inlined PaperScript associate it with myCanvas -->
<script type="text/paperscript" canvas="myCanvas">
var maxWidth = 500;
var maxHeight = 500;
var maxPoint = new Point(maxWidth,maxHeight);

var rect = new Path.Rectangle(0,0,maxWidth, maxHeight);
rect.strokeColor = 'black';
rect.strokeWidth = 3;

var map;
var sampleCirs = new Group();
var texts = new Group();
var interpRaster = new Raster('myImg');
var minTemp = 1000;
var maxTemp = -1000;

function onFrame(event)
{

}

function pointToLatLng(point)
{
var proj = map.getProjection();
var bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var neWorldXY = proj.fromLatLngToPoint(ne);
var swWorldXY = proj.fromLatLngToPoint(sw);
var curPixelX = point.x / Math.pow(2,map.getZoom());
var curPixelY = point.y / Math.pow(2,map.getZoom());
var curWorldX = curPixelX + swWorldXY.x;
var curWorldY = curPixelY + neWorldXY.y;
var curWorldPoint = new google.maps.Point(curWorldX,curWorldY);
var curLatLng = proj.fromPointToLatLng(curWorldPoint);
return curLatLng;
}

function latLngToPoint(latLng)
{
var proj = map.getProjection();
var calWorldPoint = proj.fromLatLngToPoint(latLng);
var calPixelPointx = calWorldPoint.x * Math.pow(2,map.getZoom());
var calPixelPointy = calWorldPoint.y * Math.pow(2,map.getZoom());
var bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var neWorldPoint = proj.fromLatLngToPoint(ne);
var swWorldPoint = proj.fromLatLngToPoint(sw);
var ePixelPoint = neWorldPoint.x * Math.pow(2,map.getZoom());
var nPixelPoint = neWorldPoint.y * Math.pow(2,map.getZoom());
var wPixelPoint = swWorldPoint.x * Math.pow(2,map.getZoom());
var sPixelPoint = swWorldPoint.y * Math.pow(2,map.getZoom());
var screenPixelX = calPixelPointx - wPixelPoint;
var screenPixelY = calPixelPointy - nPixelPoint;
var point = new Point(screenPixelX, screenPixelY);
return point;
}

function drawPoints(s)
{
childCount = 0;
for (var station=0;station<s.length;station++) {
if (s[station].last.hasOwnProperty('main')) {
if (s[station].last.main.hasOwnProperty('temp')) {
var lat = s[station].station.coord.lat;
var lng = s[station].station.coord.lon;
var newPoint = new Point(latLngToPoint(new google.maps.LatLng(lat, lng)));
sampleCirs.addChild(new Path.Circle(newPoint,2));
sampleCirs.children[childCount].value = s[station].last.main.temp - 273.15;
sampleCirs.children[childCount].latlng = pointToLatLng(sampleCirs.children[childCount].position);
if (sampleCirs.children[childCount].value < minTemp) {
minTemp = sampleCirs.children[childCount].value;
}
if (sampleCirs.children[childCount].value > maxTemp) {
maxTemp = sampleCirs.children[childCount].value;
}
sampleCirs.strokeColor = 'black';
sampleCirs.fillColor = 'black';
var text = new PointText(newPoint + new Point(3,-3));
text.content = Math.round(sampleCirs.children[childCount].value);
text.latlng = pointToLatLng(text.position);
texts.addChild(text);
childCount++;
}
}
}
drawRaster();
}

function drawRaster()
{
interpRaster.size = new Size(100,100);
interpRaster.fitBounds(view.bounds);
for (var i=0;i<100;i++)
{
for (var j=0;j<100;j++)
{
var wj = 0;
var wis = [];
for (var k=0;k<sampleCirs.children.length;k++)
{
var dx = sampleCirs.children[k].position.x - (i * 5);
var dy = sampleCirs.children[k].position.y - (j * 5);
var dk = Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2));
var p = 3;
var wj_inst = 1/(Math.pow(dk,p))
wj += wj_inst;
wis.push(wj_inst*sampleCirs.children[k].value);
}
var u = 0;
for (var l=0;l<wis.length;l++)
{
u += wis[l]/wj;
}
var scale = (u-minTemp)/(maxTemp-minTemp);
interpRaster.setPixel(i,j,new RgbColor(scale,0,1-scale,1));
}
}
interpRaster.opacity = 0.7;
interpRaster.latlng = map.getCenter();
interpRaster.TLlatlng = pointToLatLng(interpRaster.bounds.topLeft);
interpRaster.BRlatlng = pointToLatLng(interpRaster.bounds.bottomRight);
interpRaster.moveBelow(sampleCirs);
console.log("MAX: " + maxTemp);
console.log("MIN: " + minTemp);
}

function getData(s){
drawPoints(s);
}

$(document).ready(function() {
var style = [
{ "elementType": "geometry.fill",
"stylers": [ { "visibility": "off" } ]
},{ "featureType":
"road",
"elementType": "geometry.fill",
"stylers": [ { "visibility": "on" },
{ "color": "#000000" } ]
},{ "featureType": "water",
"elementType": "geometry.fill",
"stylers": [ { "color": "#000000" } ]
} ]

var myLatlng = new google.maps.LatLng(53.917, -122.75);
var myOptions = {
zoom: 5,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
map.setOptions({styles: style});

google.maps.event.addListener(map, 'projection_changed', function() {
$.getJSON('http://api.openweathermap.org/data/2.5/station/find?lat=53.917&lon=-122.75&cnt=30', getData); // API v.2.5
});

google.maps.event.addListener(map, 'center_changed', function() {
for (var i=0;i<sampleCirs.children.length;i++)
{
sampleCirs.children[i].position = latLngToPoint(sampleCirs.children[i].latlng);
sampleCirs.children[i].latlng = pointToLatLng(sampleCirs.children[i].position);
texts.children[i].position = latLngToPoint(texts.children[i].latlng);
texts.children[i].latlng = pointToLatLng(texts.children[i].position);
}
interpRaster.position = latLngToPoint(interpRaster.latlng);
interpRaster.latlng = pointToLatLng(interpRaster.position);
});

google.maps.event.addListener(map, 'zoom_changed', function() {
for (var i=0;i<sampleCirs.children.length;i++)
{
sampleCirs.children[i].position = latLngToPoint(sampleCirs.children[i].latlng);
sampleCirs.children[i].latlng = pointToLatLng(sampleCirs.children[i].position);
texts.children[i].position = sampleCirs.children[i].position + new Point(3,-3);
texts.children[i].latlng = pointToLatLng(texts.children[i].position);
}
var tl = latLngToPoint(interpRaster.TLlatlng);
var br = latLngToPoint(interpRaster.BRlatlng);
var bounds = new Rectangle(tl,br);

interpRaster.fitBounds(bounds);
interpRaster.TLlatlng = pointToLatLng(interpRaster.bounds.topLeft);
interpRaster.BRlatlng = pointToLatLng(interpRaster.bounds.bottomRight);
});
});

</script>
</head>
<body>
<canvas id="myCanvas" width="500" height="500"></canvas>
<div id="map" width="500" height="500"></div>
<img id="myImg"></img>
</body>
</html>

### Like this:

Like Loading...