feat(whereami): side-by-side map and weather layout
This commit is contained in:
parent
3e7c61af44
commit
6dd249dc17
1 changed files with 55 additions and 29 deletions
|
|
@ -2,19 +2,39 @@
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
|
||||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
|
||||||
<style>
|
<style>
|
||||||
#map { height: 480px; }
|
|
||||||
#location-name { min-height: 1.5em; }
|
#location-name { min-height: 1.5em; }
|
||||||
#weather { margin-top: 1.5rem; }
|
.container { max-width: 1200px; width: 95%; }
|
||||||
#weather table { border-collapse: collapse; }
|
#page-grid {
|
||||||
#weather td { padding: 0.2rem 0.8rem 0.2rem 0; }
|
display: grid;
|
||||||
#weather td:first-child { color: #888; white-space: nowrap; }
|
grid-template-columns: 3fr 2fr;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
#page-grid { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
#map { height: 520px; }
|
||||||
|
#weather-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.4rem 1rem;
|
||||||
|
}
|
||||||
|
.wx-card {
|
||||||
|
border-left: 2px solid #ddd;
|
||||||
|
padding: 0.2rem 0 0.2rem 0.5rem;
|
||||||
|
}
|
||||||
|
.wx-label { font-size: 0.72em; color: #888; margin: 0; line-height: 1.2; }
|
||||||
|
.wx-value { font-size: 1.05em; margin: 0; line-height: 1.3; }
|
||||||
|
#weather-updated { font-size: 0.75em; color: #888; margin-bottom: 0.6rem; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="container" role="main">
|
<div class="container" role="main">
|
||||||
<h2 id="location-name">Fetching location…</h2>
|
<h2 id="location-name">Fetching location…</h2>
|
||||||
<div id="map"></div>
|
|
||||||
|
|
||||||
<div id="weather"></div>
|
<div id="page-grid">
|
||||||
|
<div id="map"></div>
|
||||||
|
<div id="weather"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var map = L.map('map').setView([0, 0], 2);
|
var map = L.map('map').setView([0, 0], 2);
|
||||||
|
|
@ -52,29 +72,35 @@
|
||||||
fetch('https://jellybee.bison-lizard.ts.net/weather')
|
fetch('https://jellybee.bison-lizard.ts.net/weather')
|
||||||
.then(function(r) { if (!r.ok) throw new Error(r.status); return r.json(); })
|
.then(function(r) { if (!r.ok) throw new Error(r.status); return r.json(); })
|
||||||
.then(function(w) {
|
.then(function(w) {
|
||||||
var rows = [];
|
function fmt1(v) { return v !== undefined && v !== null ? Math.round(v * 10) / 10 : null; }
|
||||||
function row(label, val, unit) {
|
function fmt0(v) { return v !== undefined && v !== null ? Math.round(v) : null; }
|
||||||
if (val === undefined || val === null) return;
|
var cards = [
|
||||||
rows.push('<tr><td>' + label + '</td><td>' + val + (unit ? ' ' + unit : '') + '</td></tr>');
|
{ label: 'Temperature', value: fmt1(w.tempf), unit: '°F' },
|
||||||
}
|
{ label: 'Feels like', value: fmt1(w.feelsLike), unit: '°F' },
|
||||||
row('Temperature', w.tempf !== undefined ? Math.round(w.tempf * 10) / 10 : undefined, '°F');
|
{ label: 'Humidity', value: fmt0(w.humidity), unit: '%' },
|
||||||
row('Feels like', w.feelsLike !== undefined ? Math.round(w.feelsLike * 10) / 10 : undefined, '°F');
|
{ label: 'Dew point', value: fmt1(w.dewPoint), unit: '°F' },
|
||||||
row('Humidity', w.humidity !== undefined ? Math.round(w.humidity) : undefined, '%');
|
{ label: 'Wind speed', value: fmt1(w.windspeedmph), unit: 'mph' },
|
||||||
row('Dew point', w.dewPoint !== undefined ? Math.round(w.dewPoint * 10) / 10 : undefined, '°F');
|
{ label: 'Wind gust', value: fmt1(w.windgustmph), unit: 'mph' },
|
||||||
row('Wind', w.windspeedmph !== undefined ? Math.round(w.windspeedmph * 10) / 10 : undefined, 'mph');
|
{ label: 'Pressure', value: fmt1(w.baromrelin), unit: 'inHg' },
|
||||||
row('Wind gust', w.windgustmph !== undefined ? Math.round(w.windgustmph * 10) / 10 : undefined, 'mph');
|
{ label: 'UV index', value: fmt0(w.uv), unit: '' },
|
||||||
row('UV index', w.uv !== undefined ? Math.round(w.uv) : undefined, '');
|
{ label: 'Solar', value: fmt0(w.solarradiation), unit: 'W/m²' },
|
||||||
row('Solar radiation', w.solarradiation !== undefined ? Math.round(w.solarradiation) : undefined, 'W/m²');
|
{ label: 'Rain (hourly)', value: w.hourlyrainin, unit: 'in' },
|
||||||
row('Rain (hourly)', w.hourlyrainin, 'in');
|
{ label: 'Rain (daily)', value: w.dailyrainin, unit: 'in' },
|
||||||
row('Rain (daily)', w.dailyrainin, 'in');
|
{ label: 'Indoor temp', value: fmt1(w.tempinf), unit: '°F' },
|
||||||
row('Pressure (rel)', w.baromrelin, 'inHg');
|
{ label: 'Indoor humidity', value: fmt0(w.humidityin), unit: '%' },
|
||||||
row('Indoor temp', w.tempinf !== undefined ? Math.round(w.tempinf * 10) / 10 : undefined, '°F');
|
].filter(function(c) { return c.value !== null && c.value !== undefined; });
|
||||||
row('Indoor humidity', w.humidityin !== undefined ? Math.round(w.humidityin) : undefined, '%');
|
|
||||||
if (rows.length === 0) return;
|
if (cards.length === 0) return;
|
||||||
|
|
||||||
var updated = w.lastUpdated ? new Date(w.lastUpdated).toLocaleTimeString() : '';
|
var updated = w.lastUpdated ? new Date(w.lastUpdated).toLocaleTimeString() : '';
|
||||||
document.getElementById('weather').innerHTML =
|
var html = '<h3 style="margin-bottom:0.3rem">Local Weather</h3>';
|
||||||
'<h3>Local Weather' + (updated ? ' <small style="font-weight:normal;font-size:0.7em;color:#888">updated ' + updated + '</small>' : '') + '</h3>' +
|
if (updated) html += '<div id="weather-updated">updated ' + updated + '</div>';
|
||||||
'<table>' + rows.join('') + '</table>';
|
html += '<div id="weather-grid">';
|
||||||
|
cards.forEach(function(c) {
|
||||||
|
html += '<div class="wx-card"><p class="wx-label">' + c.label + '</p><p class="wx-value">' + c.value + (c.unit ? ' ' + c.unit : '') + '</p></div>';
|
||||||
|
});
|
||||||
|
html += '</div>';
|
||||||
|
document.getElementById('weather').innerHTML = html;
|
||||||
})
|
})
|
||||||
.catch(function() {});
|
.catch(function() {});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue