mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-22 19:49:31 -07:00
portrait almanac #167
This commit is contained in:
BIN
server/images/backgrounds/3-portrait.png
Normal file
BIN
server/images/backgrounds/3-portrait.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
BIN
server/images/gimp/3-portrait.xcf
Normal file
BIN
server/images/gimp/3-portrait.xcf
Normal file
Binary file not shown.
@@ -30,12 +30,13 @@ class Almanac extends WeatherDisplay {
|
||||
const superResponse = super.getData(weatherParameters, refresh);
|
||||
|
||||
// get sun/moon data
|
||||
const { sun, moon } = this.calcSunMoonData(this.weatherParameters);
|
||||
const { sun, moon, moonTransit } = this.calcSunMoonData(this.weatherParameters);
|
||||
|
||||
// store the data
|
||||
this.data = {
|
||||
sun,
|
||||
moon,
|
||||
moonTransit,
|
||||
};
|
||||
// share data
|
||||
this.getDataCallback();
|
||||
@@ -47,7 +48,9 @@ class Almanac extends WeatherDisplay {
|
||||
}
|
||||
|
||||
calcSunMoonData(weatherParameters) {
|
||||
const sun = [0, 1, 2, 3, 4, 5, 6].map((days) => SunCalc.getTimes(DateTime.local().plus({ days }).toJSDate(), weatherParameters.latitude, weatherParameters.longitude));
|
||||
const dayOffsets = [0, 1, 2, 3, 4, 5, 6];
|
||||
const sun = dayOffsets.map((days) => SunCalc.getTimes(DateTime.local().plus({ days }).toJSDate(), weatherParameters.latitude, weatherParameters.longitude));
|
||||
const moonTransit = dayOffsets.map((days) => SunCalc.getMoonTimes(DateTime.local().plus({ days }).toJSDate(), weatherParameters.latitude, weatherParameters.longitude));
|
||||
|
||||
// brute force the moon phases by scanning the next 30 days
|
||||
const moon = [];
|
||||
@@ -74,6 +77,7 @@ class Almanac extends WeatherDisplay {
|
||||
return {
|
||||
sun,
|
||||
moon,
|
||||
moonTransit,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -121,21 +125,52 @@ class Almanac extends WeatherDisplay {
|
||||
|
||||
// Generate sun data grid in reading order (left-to-right, top-to-bottom)
|
||||
|
||||
// Set day names
|
||||
// Set day names and sunset times
|
||||
const Today = DateTime.local();
|
||||
// fill all three days, even if some are hidden by non-enhanced
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
this.elem.querySelector(`.day-${i}`).textContent = Today.plus({ days: i }).toLocaleString({ weekday: 'long' });
|
||||
const portraitLines = [];
|
||||
const moonPortraitLines = [];
|
||||
// fill all days, even if some are hidden by the mode selection.
|
||||
for (let i = 0; i < 7; i += 1) {
|
||||
// format some data
|
||||
const dayName = Today.plus({ days: i }).toLocaleString({ weekday: 'long' });
|
||||
const sunrise = formatTimeForColumn(DateTime.fromJSDate(info.sun[i].sunrise));
|
||||
const sunset = formatTimeForColumn(DateTime.fromJSDate(info.sun[i].sunset));
|
||||
|
||||
const sunrise = DateTime.fromJSDate(info.sun[i].sunrise);
|
||||
const sunset = DateTime.fromJSDate(info.sun[i].sunset);
|
||||
const [sunriseFormatted, sunsetFormatted] = formatTimesForColumn([sunrise, sunset]);
|
||||
this.elem.querySelector(`.rise-${i}`).textContent = sunriseFormatted;
|
||||
this.elem.querySelector(`.set-${i}`).textContent = sunsetFormatted;
|
||||
// these only use the first 3 for standard and wide
|
||||
if (i < 3) {
|
||||
this.elem.querySelector(`.day-${i}`).textContent = dayName;
|
||||
this.elem.querySelector(`.rise-${i}`).textContent = sunrise;
|
||||
this.elem.querySelector(`.set-${i}`).textContent = sunset;
|
||||
}
|
||||
|
||||
// and also fill the portrait oriented info
|
||||
portraitLines.push(this.fillTemplate('dayname', { 'grid-item': dayName }));
|
||||
portraitLines.push(this.fillTemplate('sunrise', { 'grid-item': sunrise }));
|
||||
portraitLines.push(this.fillTemplate('sunset', { 'grid-item': sunset }));
|
||||
|
||||
// including the bonus moon rise/set data in portrait
|
||||
const moonrise = formatTimeForColumn(DateTime.fromJSDate(info.moonTransit[i].rise));
|
||||
const moonset = formatTimeForColumn(DateTime.fromJSDate(info.moonTransit[i].set));
|
||||
|
||||
moonPortraitLines.push(this.fillTemplate('dayname', { 'grid-item': dayName }));
|
||||
moonPortraitLines.push(this.fillTemplate('sunrise', { 'grid-item': moonrise }));
|
||||
moonPortraitLines.push(this.fillTemplate('sunset', { 'grid-item': moonset }));
|
||||
}
|
||||
|
||||
// add the portrait lines to the page
|
||||
const sunPortrait = this.elem.querySelector('.sun-portrait');
|
||||
const replaceable = sunPortrait.querySelectorAll(':has(.replaceable)');
|
||||
replaceable.forEach((elem) => elem.remove());
|
||||
sunPortrait.append(...portraitLines);
|
||||
|
||||
// and the moon too
|
||||
const moonPortrait = this.elem.querySelector('.moonrise.sun-portrait');
|
||||
const moonReplaceable = moonPortrait.querySelectorAll(':has(.replaceable)');
|
||||
moonReplaceable.forEach((elem) => elem.remove());
|
||||
moonPortrait.append(...moonPortraitLines);
|
||||
|
||||
// Moon data
|
||||
const days = info.moon.map((MoonPhase) => {
|
||||
const days = info.moon.map((MoonPhase, idx) => {
|
||||
const fill = {};
|
||||
|
||||
const date = MoonPhase.date.toLocaleString({ month: 'short', day: 'numeric' });
|
||||
@@ -144,7 +179,14 @@ class Almanac extends WeatherDisplay {
|
||||
fill.type = MoonPhase.phase;
|
||||
fill.icon = { type: 'img', src: this.iconPaths[MoonPhase.phase] };
|
||||
|
||||
return this.fillTemplate('day', fill);
|
||||
const filledTemplate = this.fillTemplate('day', fill);
|
||||
|
||||
// add class to hide >4 moon phases when not wide-enhanced
|
||||
if (idx > 3) {
|
||||
filledTemplate.classList.add('wide-enhanced');
|
||||
}
|
||||
|
||||
return filledTemplate;
|
||||
});
|
||||
|
||||
const daysContainer = this.elem.querySelector('.moon .days');
|
||||
@@ -181,19 +223,16 @@ const imageName = (type) => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatTimesForColumn = (times) => {
|
||||
const formatted = times.map((dt) => dt.setZone(timeZone()).toFormat('h:mm a').toUpperCase());
|
||||
|
||||
// Check if any time has a 2-digit hour (starts with '1')
|
||||
const hasTwoDigitHour = formatted.some((time) => time.startsWith('1'));
|
||||
const formatTimeForColumn = (time) => {
|
||||
// moonrise and set may not have a time each day
|
||||
if (!time.isValid) return '-';
|
||||
const formatted = time.setZone(timeZone()).toFormat('h:mm a').toUpperCase();
|
||||
|
||||
// If mixed digit lengths, pad single-digit hours with non-breaking space
|
||||
if (hasTwoDigitHour) {
|
||||
return formatted.map((time) => (time.startsWith('1') ? time : `\u00A0${time}`));
|
||||
if (formatted.length === 8) {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
// Otherwise, no padding needed
|
||||
return formatted;
|
||||
return `\u00A0${formatted}`;
|
||||
};
|
||||
|
||||
// register display
|
||||
|
||||
@@ -4,10 +4,15 @@
|
||||
#almanac-html.weather-display {
|
||||
background-image: url('../images/backgrounds/3.png');
|
||||
|
||||
// repeat the background if wide-enhanced
|
||||
// change the backgrounds for enhanced modes
|
||||
.wide.enhanced & {
|
||||
background-image: url('../images/backgrounds/3-wide-enhanced.png');
|
||||
}
|
||||
|
||||
// change background for portrait
|
||||
.portrait.enhanced & {
|
||||
background-image: url(../images/backgrounds/3-portrait.png);
|
||||
}
|
||||
}
|
||||
|
||||
.weather-display .main.almanac {
|
||||
@@ -30,6 +35,10 @@
|
||||
grid-template-columns: repeat(4, auto);
|
||||
}
|
||||
|
||||
.portrait.enhanced & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
// Reset inherited styles that interfere with grid layout
|
||||
width: auto;
|
||||
@@ -65,6 +74,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.portrait.enhanced & {
|
||||
font-size: 28pt;
|
||||
|
||||
}
|
||||
|
||||
.sun.sun-portrait {
|
||||
display: none;
|
||||
|
||||
.portrait.enhanced & {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
margin: 8px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.moon {
|
||||
position: relative;
|
||||
padding: 7px 50px;
|
||||
@@ -73,6 +99,8 @@
|
||||
.title {
|
||||
color: c.$column-header-text;
|
||||
padding-left: 13px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.days {
|
||||
@@ -93,6 +121,14 @@
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
&.wide-enhanced {
|
||||
display: none;
|
||||
|
||||
.wide.enhanced & {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
server/styles/ws.min.css
vendored
2
server/styles/ws.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,6 +14,14 @@
|
||||
<div class="grid-item time set-1"></div>
|
||||
<div class="grid-item time set-2 wide-enhanced"></div>
|
||||
</div>
|
||||
<div class="sun sun-portrait portrait-only">
|
||||
<div class="grid-item empty"></div>
|
||||
<div class="grid-item header sunrise">Sunrise</div>
|
||||
<div class="grid-item header sunset">Sunset</div>
|
||||
<div class="dayname template"><div class="grid-item row-label replaceable"></div></div>
|
||||
<div class="sunrise template"><div class="grid-item time replaceable"></div></div>
|
||||
<div class="sunset template"><div class="grid-item time replaceable"></div></div>
|
||||
</div>
|
||||
<div class="moon">
|
||||
<div class="title">Moon Data:</div>
|
||||
<div class="days">
|
||||
@@ -24,4 +32,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sun moonrise sun-portrait portrait-only">
|
||||
<div class="grid-item empty"></div>
|
||||
<div class="grid-item header sunrise">Moonrise</div>
|
||||
<div class="grid-item header sunset">Moonset</div>
|
||||
<div class="dayname template"><div class="grid-item row-label replaceable"></div></div>
|
||||
<div class="moonrise template"><div class="grid-item time replaceable"></div></div>
|
||||
<div class="moonset template"><div class="grid-item time replaceable"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user