Canvas-based seasonal weather effects + demo page
Server picks variant from Lisbon-local date (rain/petals/jacaranda/motes/leaves) and renders behind content via a canvas particle layer. Each variant has a hand-drawn silhouette so shapes are recognizable. /weather demo route exposes variant + intensity + phase pickers, locking the time-of-day phase override.
This commit is contained in:
@@ -42,6 +42,8 @@ type pageData struct {
|
||||
SiteTitle string
|
||||
Channels []Channel
|
||||
Active string // slug of active channel, "" for landing
|
||||
Weather Weather
|
||||
Phase string // when set, forces day/dawn/dusk/night and disables the clock-driven phase JS
|
||||
}
|
||||
|
||||
type channelPage struct {
|
||||
@@ -75,6 +77,7 @@ func (s *Server) base() pageData {
|
||||
return pageData{
|
||||
SiteTitle: s.cfg.SiteTitle,
|
||||
Channels: channels,
|
||||
Weather: currentWeather(time.Now()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +175,66 @@ func (s *Server) handleChannel(w http.ResponseWriter, r *http.Request, ch Channe
|
||||
s.render(w, "channel", data)
|
||||
}
|
||||
|
||||
var (
|
||||
demoVariants = []string{"rain", "petals", "jacaranda", "motes", "leaves"}
|
||||
demoIntensities = []string{"light", "medium", "heavy"}
|
||||
demoPhases = []string{"day", "dawn", "dusk", "night"}
|
||||
)
|
||||
|
||||
type weatherDemoPage struct {
|
||||
pageData
|
||||
Variants []string
|
||||
Intensities []string
|
||||
Phases []string
|
||||
Variant string
|
||||
Intensity string
|
||||
PhaseSel string
|
||||
}
|
||||
|
||||
func pickOr(v string, allowed []string, fallback string) string {
|
||||
for _, a := range allowed {
|
||||
if v == a {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func seasonForVariant(v string) string {
|
||||
switch v {
|
||||
case "rain":
|
||||
return "winter"
|
||||
case "petals", "jacaranda":
|
||||
return "spring"
|
||||
case "motes":
|
||||
return "summer"
|
||||
case "leaves":
|
||||
return "autumn"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Server) handleWeatherDemo(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
variant := pickOr(q.Get("variant"), demoVariants, "jacaranda")
|
||||
intensity := pickOr(q.Get("intensity"), demoIntensities, "heavy")
|
||||
phase := pickOr(q.Get("phase"), demoPhases, "day")
|
||||
|
||||
base := s.base()
|
||||
base.Weather = Weather{Season: seasonForVariant(variant), Variant: variant, Intensity: intensity}
|
||||
base.Phase = phase
|
||||
|
||||
s.render(w, "weather", weatherDemoPage{
|
||||
pageData: base,
|
||||
Variants: demoVariants,
|
||||
Intensities: demoIntensities,
|
||||
Phases: demoPhases,
|
||||
Variant: variant,
|
||||
Intensity: intensity,
|
||||
PhaseSel: phase,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) render(w http.ResponseWriter, page string, data any) {
|
||||
tpl, ok := s.tpls[page]
|
||||
if !ok {
|
||||
|
||||
Reference in New Issue
Block a user