better startup play/stop handing

This commit is contained in:
Matt Walsh
2020-09-17 16:34:38 -05:00
parent 36144f9eb1
commit 8f5b10664d
9 changed files with 157 additions and 174 deletions

View File

@@ -44,7 +44,7 @@ class CurrentWeather extends WeatherDisplay {
}
// we only get here if there was no error above
this.data = Object.assign({}, observations, {station: station});
this.drawCanvas();
this.setStatus(STATUS.loaded);
}
async drawCanvas () {
@@ -175,7 +175,6 @@ class CurrentWeather extends WeatherDisplay {
}));
this.finishDraw();
this.setStatus(STATUS.loaded);
}
shortConditions(condition) {

View File

@@ -41,8 +41,7 @@ class ExtendedForecast extends WeatherDisplay {
// we only get here if there was no error above
this.data = this.parseExtendedForecast(forecast.properties.periods);
this.screenIndex = 0;
this.drawCanvas();
this.setStatus(STATUS.loaded);
}
// the api provides the forecast in 12 hour increments, flatten to day increments with high and low temperatures
@@ -166,6 +165,5 @@ class ExtendedForecast extends WeatherDisplay {
}));
this.finishDraw();
this.setStatus(STATUS.loaded);
}
}

View File

@@ -55,8 +55,7 @@ class LatestObservations extends WeatherDisplay {
this.setStatus(STATUS.noData);
return;
}
this.drawCanvas();
this.setStatus(STATUS.loaded);
}
async drawCanvas() {
@@ -111,7 +110,6 @@ class LatestObservations extends WeatherDisplay {
y += 40;
});
this.finishDraw();
this.setStatus(STATUS.loaded);
}
shortenCurrentConditions(condition) {

View File

@@ -1,6 +1,6 @@
'use strict';
// navigation handles progress, next/previous and initial load messages from the parent frame
/* globals utils, _StationInfo, STATUS */
/* globals index, utils, _StationInfo, STATUS */
/* globals CurrentWeather, LatestObservations, TravelForecast, RegionalForecast, LocalForecast, ExtendedForecast, Almanac, Radar, Progress */
document.addEventListener('DOMContentLoaded', () => {
@@ -15,7 +15,6 @@ const UNITS = {
const navigation = (() => {
let weatherParameters = {};
let displays = [];
let initialLoadDone = false;
let currentUnits = UNITS.english;
let playing = false;
let progress;
@@ -25,7 +24,6 @@ const navigation = (() => {
};
const message = (data) => {
// dispatch event
if (!data.type) return;
switch (data.type) {
@@ -48,14 +46,10 @@ const navigation = (() => {
};
const postMessage = (type, message = {}) => {
const parent = window.parent;
parent.postMessage(JSON.stringify({type, message}, window.location.origin));
index.message({type, message});
};
const getWeather = async (latLon) => {
// reset statuses
initialLoadDone = false;
// get initial weather data
const point = await utils.weather.getPoint(latLon.lat, latLon.lon);
@@ -93,6 +87,11 @@ const navigation = (() => {
// update the main process for display purposes
postMessage('weatherParameters', weatherParameters);
// draw the progress canvas
progress = new Progress(-1,'progress');
await progress.drawCanvas();
progress.showCanvas();
// start loading canvases if necessary
if (displays.length === 0) {
displays = [
@@ -114,25 +113,21 @@ const navigation = (() => {
// ShowDopplerMap(this.weatherParameters);
// GetWeatherHazards3(this.weatherParameters);
// draw the progress canvas
progress = new Progress(-1,'progress');
progress.drawCanvas();
progress.showCanvas();
};
// receive a status update from a module {id, value}
const updateStatus = (value) => {
// skip if initial load
if (initialLoadDone) return;
// test for loaded status
if (value.status !== STATUS.loaded) return;
if (value.id < 0) return;
progress.drawCanvas(displays, countLoadedCanvases());
// if this is the first display and we're playing, load it up so it starts playing
if (isPlaying() && value.id === 0 && value.status === STATUS.loaded) {
navTo(msg.command.firstFrame);
}
// send loaded messaged to parent
if (countLoadedCanvases() < displays.length) return;
postMessage('loaded');
// store the display number
};
const countLoadedCanvases = () => displays.reduce((acc, display) => {
@@ -183,9 +178,9 @@ const navigation = (() => {
const navTo = (direction) => {
// test for a current display
const current = currentDisplay();
progress.hideCanvas();
if (!current) {
// special case for no active displays (typically on progress screen)
progress.hideCanvas();
displays[0].navNext(msg.command.firstFrame);
return;
}
@@ -223,14 +218,23 @@ const navigation = (() => {
const setPlaying = (newValue) => {
playing = newValue;
postMessage('isPlaying', playing);
// if we're playing and on the progress screen jump to the next screen
if (!progress) return;
if (playing && !currentDisplay()) navTo(msg.command.firstFrame);
};
// handle all navigation buttons
const handleNavButton = (button) => {
switch (button) {
case 'play':
setPlaying(true);
break;
case 'playToggle':
setPlaying(!playing);
break;
case 'stop':
setPlaying(false);
break;
case 'next':
setPlaying(false);
navTo(msg.command.nextFrame);

View File

@@ -95,12 +95,13 @@ class Progress extends WeatherDisplay {
canvasClick(e) {
const x = e.offsetX;
const y = e.offsetY;
console.log(x,y);
// eliminate off canvas and outside area clicks
if (!this.isActive()) return;
if (y < 100 || y > 410) return;
if (x < 440 || x > 570) return;
// stop playing
navigation.message('navButton', stop);
// use the y value to determine an index
const index = Math.floor((y-100)/29);
const display = navigation.getDisplay(index);

View File

@@ -67,14 +67,11 @@ class TravelForecast extends WeatherDisplay {
return;
}
this.drawCanvas(true);
this.setStatus(STATUS.loaded);
this.drawLongCanvas();
}
async drawCanvas(newData) {
// there are technically 2 canvases: the standard canvas and the extra-long canvas that contains the complete
// list of cities. The second canvas is copied into the standard canvas to create the scroll
super.drawCanvas();
async drawLongCanvas () {
// create the "long" canvas if necessary
if (!this.longCanvas) {
this.longCanvas = document.createElement('canvas');
@@ -85,61 +82,67 @@ class TravelForecast extends WeatherDisplay {
// set up variables
const cities = this.data;
// draw the long canvas only if there is new data
if (newData) {
this.longContext.clearRect(0,0,this.longCanvas.width,this.longCanvas.height);
this.longContext.clearRect(0,0,this.longCanvas.width,this.longCanvas.height);
// draw the "long" canvas with all cities
draw.box(this.longContext, 'rgb(35, 50, 112)', 0, 0, 640, _TravelCities.length*this.cityHeight);
// draw the "long" canvas with all cities
draw.box(this.longContext, 'rgb(35, 50, 112)', 0, 0, 640, _TravelCities.length*this.cityHeight);
for (let i = 0; i <= 4; i++) {
const y = i * 346;
draw.horizontalGradient(this.longContext, 0, y, 640, y + 346, '#102080', '#001040');
}
for (let i = 0; i <= 4; i++) {
const y = i * 346;
draw.horizontalGradient(this.longContext, 0, y, 640, y + 346, '#102080', '#001040');
}
await Promise.all(cities.map(async (city, index) => {
await Promise.all(cities.map(async (city, index) => {
// calculate base y value
const y = 50+this.cityHeight*index;
const y = 50+this.cityHeight*index;
// city name
draw.text(this.longContext, 'Star4000 Large Compressed', '24pt', '#FFFF00', 80, y, city.name, 2);
// city name
draw.text(this.longContext, 'Star4000 Large Compressed', '24pt', '#FFFF00', 80, y, city.name, 2);
// check for forecast data
if (city.icon) {
// check for forecast data
if (city.icon) {
// get temperatures and convert if necessary
let {low, high} = city;
let {low, high} = city;
if (navigation.units() === UNITS.metric) {
low = utils.units.fahrenheitToCelsius(low);
high = utils.units.fahrenheitToCelsius(high);
}
// convert to strings with no decimal
const lowString = Math.round(low).toString();
const highString = Math.round(high).toString();
const xLow = (500 - (lowString.length * 20));
draw.text(this.longContext, 'Star4000 Large', '24pt', '#FFFF00', xLow, y, lowString, 2);
const xHigh = (560 - (highString.length * 20));
draw.text(this.longContext, 'Star4000 Large', '24pt', '#FFFF00', xHigh, y, highString, 2);
this.gifs.push(await utils.image.superGifAsync({
src: city.icon,
loop_delay: 100,
auto_play: true,
canvas: this.longCanvas,
x: 330,
y: y - 35,
max_width: 47,
}));
} else {
draw.text(this.longContext, 'Star4000 Small', '24pt', '#FFFFFF', 400, y - 18, 'NO TRAVEL', 2);
draw.text(this.longContext, 'Star4000 Small', '24pt', '#FFFFFF', 400, y, 'DATA AVAILABLE', 2);
if (navigation.units() === UNITS.metric) {
low = utils.units.fahrenheitToCelsius(low);
high = utils.units.fahrenheitToCelsius(high);
}
}));
}
// convert to strings with no decimal
const lowString = Math.round(low).toString();
const highString = Math.round(high).toString();
const xLow = (500 - (lowString.length * 20));
draw.text(this.longContext, 'Star4000 Large', '24pt', '#FFFF00', xLow, y, lowString, 2);
const xHigh = (560 - (highString.length * 20));
draw.text(this.longContext, 'Star4000 Large', '24pt', '#FFFF00', xHigh, y, highString, 2);
this.gifs.push(await utils.image.superGifAsync({
src: city.icon,
loop_delay: 100,
auto_play: true,
canvas: this.longCanvas,
x: 330,
y: y - 35,
max_width: 47,
}));
} else {
draw.text(this.longContext, 'Star4000 Small', '24pt', '#FFFFFF', 400, y - 18, 'NO TRAVEL', 2);
draw.text(this.longContext, 'Star4000 Small', '24pt', '#FFFFFF', 400, y, 'DATA AVAILABLE', 2);
}
}));
}
async drawCanvas() {
// there are technically 2 canvases: the standard canvas and the extra-long canvas that contains the complete
// list of cities. The second canvas is copied into the standard canvas to create the scroll
super.drawCanvas();
// set up variables
const cities = this.data;
// draw the standard context
this.context.drawImage(await this.backgroundImage, 0, 0);
@@ -155,7 +158,12 @@ class TravelForecast extends WeatherDisplay {
this.context.drawImage(this.longCanvas, 0, 0, 640, 289, 0, 110, 640, 289);
this.finishDraw();
this.setStatus(STATUS.loaded);
}
async showCanvas() {
// special to travel forecast to draw the remainder of the canvas
await this.drawCanvas();
super.showCanvas();
}
// screen index change callback just runs the base count callback

View File

@@ -225,6 +225,10 @@ class WeatherDisplay {
return document.getElementById(this.elemId+'Canvas').offsetParent !== null;
}
isEnabled() {
return true;
}
// navigation timings
// totalScreens = total number of screens that are available
// baseDelay = ms to delay before re-evaluating screenIndex
@@ -246,7 +250,7 @@ class WeatherDisplay {
this.updateScreenFromBaseCount();
}
updateScreenFromBaseCount() {
async updateScreenFromBaseCount() {
// get the next screen index
let nextScreenIndex = this.screenIndexFromBaseCount();
@@ -261,11 +265,17 @@ class WeatherDisplay {
// test for no change and exit early
if (nextScreenIndex === this.screenIndex) return;
this.screenIndex = nextScreenIndex;
// test for -1 (no screen displayed yet)
if (nextScreenIndex === -1) {
this.screenIndex = 0;
} else {
this.screenIndex = nextScreenIndex;
}
// call the appropriate screen index change method
if (!this.screenIndexChange) {
this.drawCanvas();
await this.drawCanvas();
this.showCanvas();
} else {
this.screenIndexChange(this.screenIndex);
}