Now I need to style it
This commit is contained in:
+11
-1
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user