current conditions in HTML

This commit is contained in:
Matt Walsh 2022-08-02 21:39:27 -05:00
parent 6504edc253
commit ff98d970ef
11 changed files with 499 additions and 660 deletions

902
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -20,9 +20,7 @@
"devDependencies": {
"del": "^6.0.0",
"ejs": "^3.1.5",
"eslint": "^8.10.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.22.1",
"express": "^4.17.1",
"gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0",
@ -40,5 +38,9 @@
"sass": "^1.54.0",
"suncalc": "^1.8.0",
"swiped-events": "^1.1.4"
},
"dependencies": {
"eslint": "^8.21.0",
"eslint-plugin-import": "^2.26.0"
}
}
}

View file

@ -1,10 +1,10 @@
// current weather conditions display
/* globals WeatherDisplay, utils, STATUS, icons, UNITS, draw, navigation */
/* globals WeatherDisplay, utils, STATUS, icons, UNITS, navigation */
// eslint-disable-next-line no-unused-vars
class CurrentWeather extends WeatherDisplay {
constructor(navId, elemId) {
super(navId, elemId, 'Current Conditions');
super(navId, elemId, 'Current Conditions', true, true);
// pre-load background image (returns promise)
this.backgroundImage = utils.image.load('images/BackGround1_1.png');
}
@ -111,96 +111,73 @@ class CurrentWeather extends WeatherDisplay {
async drawCanvas() {
super.drawCanvas();
const fill = {};
// parse each time to deal with a change in units if necessary
const data = this.parseData();
this.context.drawImage(await this.backgroundImage, 0, 0);
draw.horizontalGradientSingle(this.context, 0, 30, 500, 90, draw.topColor1, draw.topColor2);
draw.triangle(this.context, 'rgb(28, 10, 87)', 500, 30, 450, 90, 500, 90);
draw.horizontalGradientSingle(this.context, 0, 90, 52, 399, draw.sideColor1, draw.sideColor2);
draw.horizontalGradientSingle(this.context, 584, 90, 640, 399, draw.sideColor1, draw.sideColor2);
draw.titleText(this.context, 'Current', 'Conditions');
draw.text(this.context, 'Star4000 Large', '24pt', '#FFFFFF', 170, 135, data.Temperature + String.fromCharCode(176), 2);
fill.temp = data.Temperature + String.fromCharCode(176);
let Conditions = data.observations.textDescription;
if (Conditions.length > 15) {
Conditions = this.shortConditions(Conditions);
}
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 195, 170, Conditions, 2, 'center');
fill.condition = Conditions;
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 80, 330, 'Wind:', 2);
draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 300, 330, `${data.WindDirection} ${data.WindSpeed}`, 2, 'right');
fill.wind = data.WindDirection.padEnd(3, '') + data.WindSpeed.toString().padStart(3, ' ');
if (data.WindGust) fill['wind-gusts'] = `Gusts to ${data.WindGust}`;
if (data.WindGust) draw.text(this.context, 'Star4000 Extended', '24pt', '#FFFFFF', 80, 375, `Gusts to ${data.WindGust}`, 2);
fill.location = this.data.station.properties.name.substr(0, 20);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFF00', 315, 120, this.data.station.properties.name.substr(0, 20), 2);
fill.humidity = `${data.Humidity}%`;
fill.dewpoint = data.DewPoint + String.fromCharCode(176);
fill.ceiling = (data.Ceiling === 0 ? 'Unlimited' : data.Ceiling + data.CeilingUnit);
fill.visibility = data.Visibility + data.VisibilityUnit;
fill.pressure = data.Pressure;
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 165, 'Humidity:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 165, `${data.Humidity}%`, 2, 'right');
// switch (data.PressureDirection) {
// case 'R':
// // Shadow
// draw.triangle(this.context, '#000000', 552, 302, 542, 312, 562, 312);
// draw.box(this.context, '#000000', 549, 312, 6, 15);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 205, 'Dewpoint:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 205, data.DewPoint + String.fromCharCode(176), 2, 'right');
// // Border
// draw.triangle(this.context, '#000000', 550, 300, 540, 310, 560, 310);
// draw.box(this.context, '#000000', 547, 310, 6, 15);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 245, 'Ceiling:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 245, (data.Ceiling === '' ? 'Unlimited' : data.Ceiling + data.CeilingUnit), 2, 'right');
// // Fill
// draw.triangle(this.context, '#FFFF00', 550, 301, 541, 309, 559, 309);
// draw.box(this.context, '#FFFF00', 548, 309, 4, 15);
// break;
// case 'F':
// // Shadow
// draw.triangle(this.context, '#000000', 552, 327, 542, 317, 562, 317);
// draw.box(this.context, '#000000', 549, 302, 6, 15);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 285, 'Visibility:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 285, data.Visibility + data.VisibilityUnit, 2, 'right');
// // Border
// draw.triangle(this.context, '#000000', 550, 325, 540, 315, 560, 315);
// draw.box(this.context, '#000000', 547, 300, 6, 15);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 325, 'Pressure:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 535, 325, data.Pressure, 2, 'right');
switch (data.PressureDirection) {
case 'R':
// Shadow
draw.triangle(this.context, '#000000', 552, 302, 542, 312, 562, 312);
draw.box(this.context, '#000000', 549, 312, 6, 15);
// Border
draw.triangle(this.context, '#000000', 550, 300, 540, 310, 560, 310);
draw.box(this.context, '#000000', 547, 310, 6, 15);
// Fill
draw.triangle(this.context, '#FFFF00', 550, 301, 541, 309, 559, 309);
draw.box(this.context, '#FFFF00', 548, 309, 4, 15);
break;
case 'F':
// Shadow
draw.triangle(this.context, '#000000', 552, 327, 542, 317, 562, 317);
draw.box(this.context, '#000000', 549, 302, 6, 15);
// Border
draw.triangle(this.context, '#000000', 550, 325, 540, 315, 560, 315);
draw.box(this.context, '#000000', 547, 300, 6, 15);
// Fill
draw.triangle(this.context, '#FFFF00', 550, 324, 541, 314, 559, 314);
draw.box(this.context, '#FFFF00', 548, 301, 4, 15);
break;
default:
}
// // Fill
// draw.triangle(this.context, '#FFFF00', 550, 324, 541, 314, 559, 314);
// draw.box(this.context, '#FFFF00', 548, 301, 4, 15);
// break;
// default:
// }
if (data.observations.heatIndex.value && data.HeatIndex !== data.Temperature) {
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 365, 'Heat Index:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 365, data.HeatIndex + String.fromCharCode(176), 2, 'right');
fill['heat-index-label'] = 'Heat Index:';
fill['heat-index'] = data.HeatIndex + String.fromCharCode(176);
} else if (data.observations.windChill.value && data.WindChill !== '' && data.WindChill < data.Temperature) {
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 340, 365, 'Wind Chill:', 2);
draw.text(this.context, 'Star4000 Large', 'bold 16pt', '#FFFFFF', 560, 365, data.WindChill + String.fromCharCode(176), 2, 'right');
fill['heat-index-label'] = 'Wind Chill:';
fill['heat-index'] = data.WindChill + String.fromCharCode(176);
}
if (data.Icon) {
// get main icon
this.gifs.push(await utils.image.superGifAsync({
src: data.Icon,
auto_play: true,
canvas: this.canvas,
x: 140,
y: 175,
max_width: 126,
}));
}
fill.icon = { type: 'img', src: data.Icon };
const area = this.elem.querySelector('.main');
area.innerHTML = '';
area.append(this.fillTemplate('weather', fill));
this.finishDraw();
}

View file

@ -116,18 +116,19 @@ class Hourly extends WeatherDisplay {
const startingHour = luxon.DateTime.local();
const lines = this.data.map((data, index) => {
const line = this.templates['hourly-row'].cloneNode(true);
const fillValues = {};
// hour
const hour = startingHour.plus({ hours: index });
const formattedHour = hour.toLocaleString({ weekday: 'short', hour: 'numeric' });
line.querySelector('.hour').innerHTML = formattedHour;
fillValues.hour = formattedHour;
// temperatures, convert to strings with no decimal
const temperature = Math.round(data.temperature).toString().padStart(3);
const feelsLike = Math.round(data.apparentTemperature).toString().padStart(3);
line.querySelector('.temp').innerHTML = temperature;
fillValues.temp = temperature;
// only plot apparent temperature if there is a difference
if (temperature !== feelsLike) line.querySelector('.like').innerHTML = feelsLike;
// if (temperature !== feelsLike) line.querySelector('.like').innerHTML = feelsLike;
if (temperature !== feelsLike) fillValues.like = feelsLike;
// wind
let wind = 'Calm';
@ -135,12 +136,12 @@ class Hourly extends WeatherDisplay {
const windSpeed = Math.round(data.windSpeed).toString();
wind = data.windDirection + (Array(6 - data.windDirection.length - windSpeed.length).join(' ')) + windSpeed;
}
line.querySelector('.wind').innerHTML = wind;
fillValues.wind = wind;
// image
line.querySelector('.icon img').src = data.icon;
fillValues.icon = { type: 'img', src: data.icon };
return line;
return this.fillTemplate('hourly-row', fillValues);
});
list.append(...lines);

View file

@ -93,7 +93,7 @@ const navigation = (() => {
// start loading canvases if necessary
if (displays.length === 0) {
currentWeather = new CurrentWeather(0, 'currentWeather');
currentWeather = new CurrentWeather(0, 'current-weather');
almanac = new Almanac(7, 'almanac');
displays = [
currentWeather,

View file

@ -463,4 +463,30 @@ class WeatherDisplay {
});
}
}
fillTemplate(name, fillValues) {
// get the template
const templateNode = this.templates[name];
if (!templateNode) return false;
// clone it
const template = templateNode.cloneNode(true);
Object.entries(fillValues).forEach(([key, value]) => {
// get the specified element
const elem = template.querySelector(`.${key}`);
if (!elem) return;
// fill based on type provided
if (typeof value === 'string' || typeof value === 'number') {
// string and number fill the first found selector
elem.innerHTML = value;
} else if (value?.type === 'img') {
// fill the image source
elem.querySelector('img').src = value.src;
}
});
return template;
}
}

View file

@ -188,7 +188,7 @@
font-weight: bold;
}
#current-weather-html.weather-display .main .col.right .row {
margin-bottom: 8px;
margin-bottom: 16px;
}
#current-weather-html.weather-display .main .col.right .row .label,
#current-weather-html.weather-display .main .col.right .row .value {

View file

@ -1 +1 @@
{"version":3,"sources":["scss/_weatherdisplay.scss","compiled.css","scss/_colors.scss","scss/_utils.scss","scss/_hourly.scss","scss/_current-weather.scss"],"names":[],"mappings":"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","file":"compiled.css"}
{"version":3,"sources":["scss/_weatherdisplay.scss","compiled.css","scss/_colors.scss","scss/_utils.scss","scss/_hourly.scss","scss/_current-weather.scss"],"names":[],"mappings":"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","file":"compiled.css"}

View file

@ -27,7 +27,7 @@
font-weight: bold;
.row {
margin-bottom: 8px;
margin-bottom: 16px;
.label,
.value {

View file

@ -1,36 +1,42 @@
<%- include('header.ejs', {titleDual:{ top: 'Current' , bottom: 'Conditions' }, noaaLogo: true}) %>
<div class="main has-scroll current-weather">
<div class="left col template">
<div class="temp center">79</div>
<div class="condition center">Mostly Cloudy</div>
<div class="icon center"><img src="images/CC_PartlyCloudy1.gif" /></div>
<div class="wind-container">
<div class="wind-label">Wind:</div>
<div class="wind">WNW 11</div>
<div class="weather template">
<div class="left col">
<div class="temp center"></div>
<div class="condition center"></div>
<div class="icon center"><img src="" /></div>
<div class="wind-container">
<div class="wind-label">Wind:</div>
<div class="wind"></div>
</div>
<div class="wind-gusts"></div>
</div>
<div class="wind-gusts">Gusts to 22</div>
</div>
<div class="right col template">
<div class="location">Chicago / West Chica</div>
<div class="row">
<div class="label">Humidity:</div>
<div class="humidity value">47%</div>
</div>
<div class="row">
<div class="label">Dewpoint:</div>
<div class="dewpoint value">57%</div>
</div>
<div class="row">
<div class="label">Ceiling:</div>
<div class="ceiling value">5000ft.</div>
</div>
<div class="row">
<div class="label">Visibility:</div>
<div class="visibility value">10 mi.</div>
</div>
<div class="row">
<div class="label">Pressure:</div>
<div class="pressure value">30.05</div>
<div class="right col">
<div class="location"></div>
<div class="row">
<div class="label">Humidity:</div>
<div class="humidity value"></div>
</div>
<div class="row">
<div class="label">Dewpoint:</div>
<div class="dewpoint value"></div>
</div>
<div class="row">
<div class="label">Ceiling:</div>
<div class="ceiling value"></div>
</div>
<div class="row">
<div class="label">Visibility:</div>
<div class="visibility value"></div>
</div>
<div class="row">
<div class="label">Pressure:</div>
<div class="pressure value"></div>
</div>
<div class="row">
<div class="heat-index-label label"></div>
<div class="heat-index value"></div>
</div>
</div>
</div>
</div>

View file

@ -16,18 +16,19 @@
"cSpell.enabled": true,
"cSpell.words": [
"'storm",
"arcgis",
"Battaglia",
"devbridge",
"gifs",
"ltrim",
"Noaa",
"nosleep",
"Pngs",
"rtrim",
"T",
"T'storm",
"Visib",
"arcgis",
"devbridge",
"ltrim",
"nosleep",
"rtrim",
"uscomp"
"uscomp",
"Visib"
],
"cSpell.ignorePaths": [
"**/package-lock.json",