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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more