remove current weather scroll canvas and almanac-outlook
This commit is contained in:
parent
80958226ce
commit
eae3b321c7
|
@ -9,7 +9,6 @@ class Almanac extends WeatherDisplay {
|
||||||
|
|
||||||
// pre-load background images (returns promises)
|
// pre-load background images (returns promises)
|
||||||
this.backgroundImage0 = utils.image.load('images/BackGround3_1.png');
|
this.backgroundImage0 = utils.image.load('images/BackGround3_1.png');
|
||||||
this.backgroundImage1 = utils.image.load('images/BackGround1_1.png');
|
|
||||||
|
|
||||||
// load all images in parallel (returns promises)
|
// load all images in parallel (returns promises)
|
||||||
this.moonImages = [
|
this.moonImages = [
|
||||||
|
@ -19,32 +18,20 @@ class Almanac extends WeatherDisplay {
|
||||||
utils.image.load('images/2/First-Quarter.gif'),
|
utils.image.load('images/2/First-Quarter.gif'),
|
||||||
];
|
];
|
||||||
|
|
||||||
this.timing.totalScreens = 2;
|
this.timing.totalScreens = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getData(_weatherParameters) {
|
async getData(_weatherParameters) {
|
||||||
super.getData(_weatherParameters);
|
super.getData(_weatherParameters);
|
||||||
const weatherParameters = _weatherParameters ?? this.weatherParameters;
|
const weatherParameters = _weatherParameters ?? this.weatherParameters;
|
||||||
|
|
||||||
// get images for outlook
|
|
||||||
const imagePromises = [
|
|
||||||
utils.image.load('https://www.cpc.ncep.noaa.gov/products/predictions/30day/off14_temp.gif', true),
|
|
||||||
utils.image.load('https://www.cpc.ncep.noaa.gov/products/predictions/30day/off14_prcp.gif', true),
|
|
||||||
];
|
|
||||||
|
|
||||||
// get sun/moon data
|
// get sun/moon data
|
||||||
const { sun, moon } = this.calcSunMoonData(weatherParameters);
|
const { sun, moon } = this.calcSunMoonData(weatherParameters);
|
||||||
|
|
||||||
// process images for outlook
|
|
||||||
const [outlookTemp, outlookPrecip] = await Promise.all(imagePromises);
|
|
||||||
|
|
||||||
const outlook = Almanac.parseOutlooks(weatherParameters.latitude, weatherParameters.longitude, outlookTemp, outlookPrecip);
|
|
||||||
|
|
||||||
// store the data
|
// store the data
|
||||||
this.data = {
|
this.data = {
|
||||||
sun,
|
sun,
|
||||||
moon,
|
moon,
|
||||||
outlook,
|
|
||||||
};
|
};
|
||||||
// update status
|
// update status
|
||||||
this.setStatus(STATUS.loaded);
|
this.setStatus(STATUS.loaded);
|
||||||
|
@ -127,115 +114,6 @@ class Almanac extends WeatherDisplay {
|
||||||
return { phase: phaseName, date: moonDate };
|
return { phase: phaseName, date: moonDate };
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the color of the pixel to determine the outlook
|
|
||||||
static parseOutlooks(lat, lon, temp, precip) {
|
|
||||||
const { DateTime } = luxon;
|
|
||||||
const month = DateTime.local();
|
|
||||||
const thisMonth = month.toLocaleString({ month: 'short' });
|
|
||||||
const nextMonth = month.plus({ months: 1 }).toLocaleString({ month: 'short' });
|
|
||||||
|
|
||||||
// draw the images on the canvases
|
|
||||||
const tempContext = utils.image.drawLocalCanvas(temp);
|
|
||||||
const precipContext = utils.image.drawLocalCanvas(precip);
|
|
||||||
|
|
||||||
// get the color from each canvas
|
|
||||||
const tempColor = Almanac.getOutlookColor(lat, lon, tempContext);
|
|
||||||
const precipColor = Almanac.getOutlookColor(lat, lon, precipContext);
|
|
||||||
|
|
||||||
return {
|
|
||||||
thisMonth,
|
|
||||||
nextMonth,
|
|
||||||
temperature: Almanac.getOutlookTemperatureIndicator(tempColor),
|
|
||||||
precipitation: Almanac.getOutlookPrecipitationIndicator(precipColor),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getOutlookColor(lat, lon, context) {
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
|
|
||||||
// The height is in the range of latitude 75'N (top) - 15'N (bottom)
|
|
||||||
y = ((75 - lat) / 53) * 707;
|
|
||||||
|
|
||||||
if (lat < 48.83) {
|
|
||||||
y -= Math.abs(48.83 - lat) * 2.9;
|
|
||||||
}
|
|
||||||
if (lon < -100.46) {
|
|
||||||
y -= Math.abs(-100.46 - lon) * 1.7;
|
|
||||||
} else {
|
|
||||||
y -= Math.abs(-100.46 - lon) * 1.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The width is in the range of the longitude ???
|
|
||||||
x = ((-155 - lon) / -110) * 719; // -155 - -40
|
|
||||||
|
|
||||||
if (lon < -100.46) {
|
|
||||||
x -= Math.abs(-100.46 - lon) * 1;
|
|
||||||
|
|
||||||
if (lat > 40) {
|
|
||||||
x += Math.abs(40 - lat) * 4;
|
|
||||||
} else {
|
|
||||||
x -= Math.abs(40 - lat) * 4;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
x += Math.abs(-100.46 - lon) * 2;
|
|
||||||
|
|
||||||
if (lat < 36 && lon > -90) {
|
|
||||||
x += Math.abs(36 - lat) * 8;
|
|
||||||
} else {
|
|
||||||
x -= Math.abs(36 - lat) * 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The further left and right from lat 45 and lon -97 the y increases
|
|
||||||
x = Math.round(x);
|
|
||||||
y = Math.round(y);
|
|
||||||
|
|
||||||
// Determine if there is any "non-white" colors around the area.
|
|
||||||
// Search a 16x16 region.
|
|
||||||
for (let colorX = x - 8; colorX <= x + 8; colorX += 1) {
|
|
||||||
for (let colorY = y - 8; colorY <= y + 8; colorY += 1) {
|
|
||||||
const pixelColor = Almanac.getPixelColor(context, colorX, colorY);
|
|
||||||
if ((pixelColor.r !== 0 && pixelColor.g !== 0 && pixelColor.b !== 0)
|
|
||||||
|| (pixelColor.r !== 255 && pixelColor.g !== 255 && pixelColor.b !== 255)) {
|
|
||||||
return pixelColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get rgb values of a pixel
|
|
||||||
static getPixelColor(context, x, y) {
|
|
||||||
const pixelData = context.getImageData(x, y, 1, 1).data;
|
|
||||||
return {
|
|
||||||
r: pixelData[0],
|
|
||||||
g: pixelData[1],
|
|
||||||
b: pixelData[2],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// get temperature outlook from color
|
|
||||||
static getOutlookTemperatureIndicator(pixelColor) {
|
|
||||||
if (pixelColor.b > pixelColor.r) {
|
|
||||||
return 'Below Normal';
|
|
||||||
} if (pixelColor.r > pixelColor.b) {
|
|
||||||
return 'Above Normal';
|
|
||||||
}
|
|
||||||
return 'Normal';
|
|
||||||
}
|
|
||||||
|
|
||||||
// get precipitation outlook from color
|
|
||||||
static getOutlookPrecipitationIndicator(pixelColor) {
|
|
||||||
if (pixelColor.g > pixelColor.r) {
|
|
||||||
return 'Above Normal';
|
|
||||||
} if (pixelColor.r > pixelColor.g) {
|
|
||||||
return 'Below Normal';
|
|
||||||
}
|
|
||||||
return 'Normal';
|
|
||||||
}
|
|
||||||
|
|
||||||
async drawCanvas() {
|
async drawCanvas() {
|
||||||
super.drawCanvas();
|
super.drawCanvas();
|
||||||
const info = this.data;
|
const info = this.data;
|
||||||
|
@ -246,74 +124,48 @@ class Almanac extends WeatherDisplay {
|
||||||
// extract moon images
|
// extract moon images
|
||||||
const [FullMoonImage, LastMoonImage, NewMoonImage, FirstMoonImage] = await Promise.all(this.moonImages);
|
const [FullMoonImage, LastMoonImage, NewMoonImage, FirstMoonImage] = await Promise.all(this.moonImages);
|
||||||
|
|
||||||
switch (this.screenIndex) {
|
// sun and moon data
|
||||||
case 1: {
|
this.context.drawImage(await this.backgroundImage0, 0, 0);
|
||||||
this.context.drawImage(await this.backgroundImage1, 0, 0);
|
draw.horizontalGradientSingle(this.context, 0, 30, 500, 90, draw.topColor1, draw.topColor2);
|
||||||
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.triangle(this.context, 'rgb(28, 10, 87)', 500, 30, 450, 90, 500, 90);
|
draw.horizontalGradientSingle(this.context, 0, 90, 640, 190, draw.sideColor1, draw.sideColor2);
|
||||||
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, 'Almanac', 'Outlook');
|
draw.titleText(this.context, 'Almanac', 'Astronomical');
|
||||||
|
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 320, 180, '30 Day Outlook', 2, 'center');
|
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 320, 120, Today.toLocaleString({ weekday: 'long' }), 2, 'center');
|
||||||
|
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 500, 120, Tomorrow.toLocaleString({ weekday: 'long' }), 2, 'center');
|
||||||
|
|
||||||
const DateRange = `MID-${info.outlook.thisMonth.toUpperCase()} TO MID-${info.outlook.nextMonth.toUpperCase()}`;
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 150, 'Sunrise:', 2);
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 320, 220, DateRange, 2, 'center');
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 270, 150, DateTime.fromJSDate(info.sun[0].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
||||||
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 450, 150, DateTime.fromJSDate(info.sun[1].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
||||||
|
|
||||||
const Temperature = info.outlook.temperature;
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 180, ' Sunset:', 2);
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 300, `Temperatures: ${Temperature}`, 2);
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 270, 180, DateTime.fromJSDate(info.sun[0].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
||||||
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 450, 180, DateTime.fromJSDate(info.sun[1].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
||||||
|
|
||||||
const Precipitation = info.outlook.precipitation;
|
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 70, 220, 'Moon Data:', 2);
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 380, `Precipitation: ${Precipitation}`, 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
// sun and moon data
|
|
||||||
this.context.drawImage(await this.backgroundImage0, 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, 640, 190, draw.sideColor1, draw.sideColor2);
|
|
||||||
|
|
||||||
draw.titleText(this.context, 'Almanac', 'Astronomical');
|
info.moon.forEach((MoonPhase, Index) => {
|
||||||
|
const date = MoonPhase.date.toLocaleString({ month: 'short', day: 'numeric' });
|
||||||
|
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 320, 120, Today.toLocaleString({ weekday: 'long' }), 2, 'center');
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 120 + Index * 130, 260, MoonPhase.phase, 2, 'center');
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 500, 120, Tomorrow.toLocaleString({ weekday: 'long' }), 2, 'center');
|
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 120 + Index * 130, 390, date, 2, 'center');
|
||||||
|
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 150, 'Sunrise:', 2);
|
const image = (() => {
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 270, 150, DateTime.fromJSDate(info.sun[0].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
switch (MoonPhase.phase) {
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 450, 150, DateTime.fromJSDate(info.sun[1].sunrise).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
case 'Full':
|
||||||
|
return FullMoonImage;
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 70, 180, ' Sunset:', 2);
|
case 'Last':
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 270, 180, DateTime.fromJSDate(info.sun[0].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
return LastMoonImage;
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 450, 180, DateTime.fromJSDate(info.sun[1].sunset).toLocaleString(DateTime.TIME_SIMPLE).toLowerCase(), 2);
|
case 'New':
|
||||||
|
return NewMoonImage;
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFF00', 70, 220, 'Moon Data:', 2);
|
case 'First':
|
||||||
|
default:
|
||||||
info.moon.forEach((MoonPhase, Index) => {
|
return FirstMoonImage;
|
||||||
const date = MoonPhase.date.toLocaleString({ month: 'short', day: 'numeric' });
|
}
|
||||||
|
})();
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 120 + Index * 130, 260, MoonPhase.phase, 2, 'center');
|
this.context.drawImage(image, 75 + Index * 130, 270);
|
||||||
draw.text(this.context, 'Star4000', '24pt', '#FFFFFF', 120 + Index * 130, 390, date, 2, 'center');
|
});
|
||||||
|
|
||||||
const image = (() => {
|
|
||||||
switch (MoonPhase.phase) {
|
|
||||||
case 'Full':
|
|
||||||
return FullMoonImage;
|
|
||||||
case 'Last':
|
|
||||||
return LastMoonImage;
|
|
||||||
case 'New':
|
|
||||||
return NewMoonImage;
|
|
||||||
case 'First':
|
|
||||||
default:
|
|
||||||
return FirstMoonImage;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
this.context.drawImage(image, 75 + Index * 130, 270);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.finishDraw();
|
this.finishDraw();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* globals draw, navigation, utils */
|
/* globals navigation, utils */
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const currentWeatherScroll = (() => {
|
const currentWeatherScroll = (() => {
|
||||||
|
@ -6,23 +6,13 @@ const currentWeatherScroll = (() => {
|
||||||
const degree = String.fromCharCode(176);
|
const degree = String.fromCharCode(176);
|
||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
let context; // currently active context
|
|
||||||
let blankDrawArea; // original state of context
|
|
||||||
let interval;
|
let interval;
|
||||||
let screenIndex = 0;
|
let screenIndex = 0;
|
||||||
|
|
||||||
// start drawing conditions
|
// start drawing conditions
|
||||||
// reset starts from the first item in the text scroll list
|
// reset starts from the first item in the text scroll list
|
||||||
const start = (_context) => {
|
const start = () => {
|
||||||
// store see if the context is new
|
// store see if the context is new
|
||||||
if (context && _context !== context) {
|
|
||||||
// clean the outgoing context
|
|
||||||
cleanLastContext();
|
|
||||||
// store the new blank context
|
|
||||||
blankDrawArea = _context.getImageData(0, 405, 640, 75);
|
|
||||||
}
|
|
||||||
// store the context locally
|
|
||||||
context = _context;
|
|
||||||
|
|
||||||
// set up the interval if needed
|
// set up the interval if needed
|
||||||
if (!interval) {
|
if (!interval) {
|
||||||
|
@ -34,18 +24,10 @@ const currentWeatherScroll = (() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const stop = (reset) => {
|
const stop = (reset) => {
|
||||||
cleanLastContext();
|
|
||||||
if (interval) interval = clearInterval(interval);
|
if (interval) interval = clearInterval(interval);
|
||||||
if (reset) screenIndex = 0;
|
if (reset) screenIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanLastContext = () => {
|
|
||||||
if (!context) return;
|
|
||||||
if (blankDrawArea) context.putImageData(blankDrawArea, 0, 405);
|
|
||||||
blankDrawArea = undefined;
|
|
||||||
context = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// increment interval, roll over
|
// increment interval, roll over
|
||||||
const incrementInterval = () => {
|
const incrementInterval = () => {
|
||||||
screenIndex = (screenIndex + 1) % (screens.length);
|
screenIndex = (screenIndex + 1) % (screens.length);
|
||||||
|
@ -60,9 +42,6 @@ const currentWeatherScroll = (() => {
|
||||||
// nothing to do if there's no data yet
|
// nothing to do if there's no data yet
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
// clean up any old text
|
|
||||||
if (context && blankDrawArea) context.putImageData(blankDrawArea, 0, 405);
|
|
||||||
|
|
||||||
drawCondition(screens[screenIndex](data));
|
drawCondition(screens[screenIndex](data));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,10 +87,6 @@ const currentWeatherScroll = (() => {
|
||||||
|
|
||||||
// internal draw function with preset parameters
|
// internal draw function with preset parameters
|
||||||
const drawCondition = (text) => {
|
const drawCondition = (text) => {
|
||||||
if (context) {
|
|
||||||
draw.text(context, 'Star4000', '24pt', '#ffffff', 70, 430, text, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update all html scroll elements
|
// update all html scroll elements
|
||||||
utils.elem.forEach('.weather-display .scroll .fixed', (elem) => {
|
utils.elem.forEach('.weather-display .scroll .fixed', (elem) => {
|
||||||
elem.innerHTML = text;
|
elem.innerHTML = text;
|
||||||
|
|
|
@ -196,7 +196,7 @@ class WeatherDisplay {
|
||||||
if (OkToDrawLogoImage) this.drawLogoImage();
|
if (OkToDrawLogoImage) this.drawLogoImage();
|
||||||
if (OkToDrawNoaaImage) this.drawNoaaImage();
|
if (OkToDrawNoaaImage) this.drawNoaaImage();
|
||||||
if (OkToDrawCurrentConditions) {
|
if (OkToDrawCurrentConditions) {
|
||||||
currentWeatherScroll.start(this.context);
|
currentWeatherScroll.start();
|
||||||
} else {
|
} else {
|
||||||
// cause a reset if the progress screen is displayed
|
// cause a reset if the progress screen is displayed
|
||||||
currentWeatherScroll.stop(this.elemId === 'progress');
|
currentWeatherScroll.stop(this.elemId === 'progress');
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
<div class="instructions">Enter your location above to continue</div>
|
<div class="instructions">Enter your location above to continue</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="progress-html" class="weather-display show">
|
<div id="progress-html" class="weather-display">
|
||||||
<%- include('partials/progress.ejs') %>
|
<%- include('partials/progress.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="hourly-html" class="weather-display">
|
<div id="hourly-html" class="weather-display">
|
||||||
|
|
Loading…
Reference in a new issue