Now I need to style it

This commit is contained in:
Lani Aung
2025-06-12 19:37:52 -07:00
parent 8b828f79fd
commit 30043f755a
3 changed files with 122 additions and 101 deletions
+11 -1
View File
@@ -8,14 +8,24 @@ body {
#weather-panel {
border-radius: 50px;
box-shadow: #999a 0 0 25px;
color: #fff;
font-family: Verdana, sans-serif;
font-weight: bold;
height: 500px;
left: calc(50% - 250px);
padding: 40px;
position: absolute;
text-shadow: #fff 0 0 5px, #fff 0 0 5px, #fff 0 0 5px, #fff 0 0 5px;
text-shadow: #000 1px 1px,
#000 -1px 1px,
#000 -1px -1px,
#000 1px -1px;
top: calc(50% - 250px);
width: 500px;
z-index: 10;
@supports (-webkit-text-stroke: 1px #000) {
-webkit-text-stroke: 1px #000;
-webkit-text-fill-color: #fff;
}
}
}
+53 -51
View File
@@ -1,4 +1,5 @@
import { fetchWeatherApi } from 'openmeteo'
import { fetchWeatherApi } from "openmeteo"
import { VariablesWithTime } from "@openmeteo/sdk/variables-with-time"
export default class Weather {
private readonly apiUrl = "https://api.open-meteo.com/v1/forecast"
@@ -15,53 +16,66 @@ export default class Weather {
this.options = new WeatherOptions(latitude ?? 47.61002138071677, longitude ?? -122.17906310779568)
const me = this
setInterval(() => me.fetchWeather().then(() => me.setDisplay()), 60 * 1000)
setInterval(() => me.fetchWeather().then(() => me.setDisplay()), 60000)
me.fetchWeather().then(() => me.setDisplay())
}
async fetchWeather(): Promise<void> {
const me = this
const parameters: any = { ...me.options }
let getData = false
if (!me.doFetchData(parameters)) return
const responses = await fetchWeatherApi(me.apiUrl, parameters)
for (const response of responses) {
const current = response.current()
const hourly = response.hourly()
const daily = response.daily()
if (current != null) me.setCurrentData(current)
if (hourly != null) me.setHourlyData(hourly)
if (daily != null) me.setDailyData(daily)
}
}
private doFetchData(parameters: any): boolean {
const me = this
if (!me.lastFetched) {
parameters["daily"] = me.dailyVariables
parameters["hourly"] = me.hourlyVariables
parameters["current"] = me.currentVariables
me.lastFetched = new LastFetched()
getData = true
return true
} else {
// Reasonable-ish timers?
if (me.lastFetched.minutesSinceCurrent() > 15) {
// Weather data is updated :00, :15, :30, :45 so wait at least a minute
if (me.lastFetched.current.getMinutes() % 15 < 5) {
const now = new Date()
// Make sure data is over 5 minutes old at least
if ((now.getTime() - me.lastFetched.current.getTime()) > 300000) {
parameters["current"] = me.currentVariables
me.lastFetched.current = new Date()
getData = true
return true
}
}
// Reasonable-ish timers?
if (me.lastFetched.hoursSinceHourly() > 3) {
parameters["hourly"] = me.hourlyVariables
me.lastFetched.hourly = new Date()
getData = true
return true
}
if (me.lastFetched.hoursSinceDaily() > 8) {
parameters["daily"] = me.dailyVariables
me.lastFetched.daily = new Date()
getData = true
return true
}
}
if (!getData) return
return false
}
const responses = await fetchWeatherApi(me.apiUrl, parameters)
for (const response of responses) {
const utcOffsetSeconds = response.utcOffsetSeconds()
const current = response.current()
const hourly = response.hourly()
const daily = response.daily()
if (current != null) {
me.current = {
private setCurrentData(current: VariablesWithTime) {
this.current = {
time: new Date(Number(current.time()) * 1000),
temperature: current.variables(0)!.value(),
humidity: current.variables(1)!.value(),
@@ -74,16 +88,16 @@ export default class Weather {
}
}
if (hourly != null) {
private setHourlyData(hourly: VariablesWithTime) {
const length = Number(hourly.timeEnd() - hourly.time()) / hourly.interval()
const temperatures = hourly.variables(0)!.valuesArray()
const precipitationTotals = hourly.variables(1)!.valuesArray()
const precipitationProbabilities = hourly.variables(2)!.valuesArray()
me.hourly.length = 0
this.hourly.length = 0
for (let i = 0; i < length; i++) {
me.hourly.push({
time: new Date((Number(hourly.time()) + i * hourly.interval() + utcOffsetSeconds) * 1000),
this.hourly.push({
time: new Date((Number(hourly.time()) + i * hourly.interval()) * 1000),
temperature: temperatures[i],
precipitation: precipitationTotals[i],
precipitationProbability: precipitationProbabilities[i]
@@ -91,7 +105,7 @@ export default class Weather {
}
}
if (daily != null) {
private setDailyData(daily: VariablesWithTime) {
const length = Number(daily.timeEnd() - daily.time()) / daily.interval()
const maxTemperatures = daily.variables(0)!.valuesArray()
const minTemperatures = daily.variables(1)!.valuesArray()
@@ -104,10 +118,10 @@ export default class Weather {
const maxWindGusts = daily.variables(8)!.valuesArray()
const prominentWindDirections = daily.variables(9)!.valuesArray()
me.daily.length = 0
this.daily.length = 0
for (let i = 0; i < length; i++) {
me.daily.push({
this.daily.push({
time: new Date((Number(daily.time()) + i * daily.interval()) * 1000),
maxTemperature: maxTemperatures[i],
minTemperature: minTemperatures[i],
@@ -122,8 +136,6 @@ export default class Weather {
})
}
}
}
}
private setDisplay() {
let panel = document.getElementById("weather-panel")
@@ -134,31 +146,25 @@ export default class Weather {
}
while (panel.firstChild) panel.removeChild(panel.firstChild)
this.setDisplayCurrent(panel)
}
private setDisplayCurrent(panel: HTMLElement) {
const currentSection = document.createElement("section")
currentSection.id = "current-section"
panel.appendChild(currentSection)
this.setDisplayCurrent(currentSection)
}
private setDisplayCurrent(section: HTMLElement) {
const header = document.createElement("header")
header.textContent = "Current"
section.appendChild(header)
const list = document.createElement("dl")
for (let key of Object.keys(this.current)) {
const term = document.createElement("dt")
term.textContent = key
const value = document.createElement("dd")
value.textContent = (this.current as any)[key]
list.append(term, value)
}
section.appendChild(list)
private InCardinals(direction: number): string {
if (direction > 337.5 || direction <= 22.5) return "N"
if (direction > 22.5 || direction <= 67.5) return "NE"
if (direction > 67.5 || direction <= 112.5) return "E"
if (direction > 112.5 || direction <= 157.5) return "SE"
if (direction > 157.5 || direction <= 202.5) return "S"
if (direction > 202.5 || direction <= 249.5) return "SW"
if (direction > 249.5 || direction <= 294.5) return "W"
if (direction > 294.5 || direction <= 337.5) return "NW"
return null
}
}
@@ -215,10 +221,6 @@ class LastFetched {
hourly: Date = new Date()
daily: Date = new Date()
minutesSinceCurrent(): number {
return (new Date().getTime() - this.current.getTime()) / 60000
}
hoursSinceHourly(): number {
return (new Date().getTime() - this.hourly.getTime()) / 3600000
}
+10 -1
View File
@@ -9,13 +9,22 @@ html #weather-panel,
body #weather-panel {
border-radius: 50px;
box-shadow: #999a 0 0 25px;
color: #fff;
font-family: Verdana, sans-serif;
font-weight: bold;
height: 500px;
left: calc(50% - 250px);
padding: 40px;
position: absolute;
text-shadow: #fff 0 0 5px, #fff 0 0 5px, #fff 0 0 5px, #fff 0 0 5px;
text-shadow: #000 1px 1px, #000 -1px 1px, #000 -1px -1px, #000 1px -1px;
top: calc(50% - 250px);
width: 500px;
z-index: 10;
}
@supports (-webkit-text-stroke: 1px #000) {
html #weather-panel,
body #weather-panel {
-webkit-text-stroke: 1px #000;
-webkit-text-fill-color: #fff;
}
}