Published
Edited
Mar 4, 2021
Insert cell
Insert cell
openweathermap = {
// DOM CONTAINER
const container = html`<div style="height:400px;">`;
yield container;
const map = L.map(container);

// BASEMAP
map.fitBounds(ldnBounds);
L.tileLayer(
'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}{r}.{ext}',
{
attribution:
'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 20,
ext: 'png'
}
).addTo(map);

// BOUNDARY
L.geoJSON(glaBoundary, { color: 'purple', weight: 1, fill: false }).addTo(
map
);

// VARS
let maxTemp = 0; // raise up from too low
let minTemp = 10000; // come down from too high
const rectangles = [];
const promises = [];

// FUNCTIONS
const col = val => {
return val < 1 ? 'blue' : 'red';
};
const sequentialScale = d3
.scaleSequential()
.domain([osgbGrid5k.features.length, 0]) // there are 91 osgb 5k grid squares overlaying ldn
.interpolator(d3.interpolateRdYlBu);

// GET LATEST TEMPERATURE DATA
Object.values(L.geoJSON(osgbGrid5k.features)._layers).map(lyr => {
promises.push(
d3
.json(getUrl(lyr._bounds.getCenter().lng, lyr._bounds.getCenter().lat))
.then(res => {
const temp = res.main.temp;
const feels_like = res.main.feels_like;

if (temp > maxTemp) {
maxTemp = temp;
}
if (temp < minTemp) {
minTemp = temp;
}
const rect = L.rectangle(
[lyr._bounds.getSouthWest(), lyr._bounds.getNorthEast()],
{
stroke: true,
color: 'gray',
strokeOpacity: 0.2,
weight: 0.5
}
).bindTooltip(`${temp} &#8451;, feels like ${feels_like} &#8451;`);
rect.addTo(map);
rectangles.push(rect);
rect.temp = temp;
rect.feels_like = feels_like;
})
);
});

// COLOUR IN THE GRID BY LATEST TEMPERATURE READINGS
Promise.all(promises).then(vals => {
rectangles.sort((a, b) => {
return a.feels_like - b.feels_like;
});
rectangles.map((r, i) => {
const colour = sequentialScale(i);
r.setStyle({
fillColor: colour,
fillOpacity: 0.5,
color: colour,
opacity: 0.5
});
});

// SET LEGEND FROM LATEST TEMPERATURE READINGS
const legend = L.control({ position: 'bottomright' });
legend.onAdd = function(map) {
const div = L.DomUtil.create('div', 'info legend'),
grades = rectangles.map(r => r.feels_like);
div.innerHTML = '<h2>&#127751;feels like&#127774;</h2>';
for (let i = grades.length; i >= 0; i = i - 10) {
div.innerHTML += `<i style="background:${sequentialScale(i - 1)}"></i>${
grades[i - 1]
}${
grades[i - 1]
? (grades[i] ? '&ndash;' + grades[i] : '') + ' &#8451;<br>'
: '+'
}`;
}
return div;
};
legend.addTo(map);
});
}
Insert cell
Insert cell
Insert cell
md`# css`
Insert cell
Insert cell
md`# functions`
Insert cell
Insert cell
md`# data`
Insert cell
Insert cell
getUrl = (lng, lat) =>
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${apikey}&units=metric`
Insert cell
ldnBounds = L.geoJSON(glaBoundary).getBounds()
Insert cell
glaBoundary = FileAttachment('gla.geojson').json()
Insert cell
osgbGrid5k = FileAttachment('osgb-grid-5k-4326@1.json').json()
Insert cell
Insert cell
Insert cell
d3 = require('d3@latest')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more