2020-09-04 18:02:20 +00:00
|
|
|
// regional forecast and observations
|
|
|
|
// type 0 = observations, 1 = first forecast, 2 = second forecast
|
|
|
|
|
2022-08-05 01:50:14 +00:00
|
|
|
/* globals WeatherDisplay, utils, STATUS, icons, UNITS, navigation, luxon, StationInfo, RegionalCities */
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
class RegionalForecast extends WeatherDisplay {
|
2020-10-29 21:44:28 +00:00
|
|
|
constructor(navId, elemId) {
|
2022-11-22 03:50:22 +00:00
|
|
|
super(navId, elemId, 'Regional Forecast', true);
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-09-08 15:23:18 +00:00
|
|
|
// timings
|
|
|
|
this.timing.totalScreens = 3;
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
async getData(_weatherParameters) {
|
|
|
|
super.getData(_weatherParameters);
|
|
|
|
const weatherParameters = _weatherParameters ?? this.weatherParameters;
|
2020-09-25 14:55:29 +00:00
|
|
|
|
2022-08-05 03:12:08 +00:00
|
|
|
// pre-load the base map
|
2022-08-05 03:26:09 +00:00
|
|
|
let baseMap = 'images/Basemap2.png';
|
2020-10-16 20:30:27 +00:00
|
|
|
if (weatherParameters.state === 'HI') {
|
2022-08-05 03:26:09 +00:00
|
|
|
baseMap = 'images/HawaiiRadarMap4.png';
|
2020-10-16 20:30:27 +00:00
|
|
|
} else if (weatherParameters.state === 'AK') {
|
2022-08-05 03:26:09 +00:00
|
|
|
baseMap = 'images/AlaskaRadarMap6.png';
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
2022-08-05 03:26:09 +00:00
|
|
|
this.elem.querySelector('.map img').src = baseMap;
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-09-08 15:23:18 +00:00
|
|
|
// map offset
|
|
|
|
const offsetXY = {
|
|
|
|
x: 240,
|
|
|
|
y: 117,
|
|
|
|
};
|
|
|
|
// get user's location in x/y
|
2022-08-05 03:12:08 +00:00
|
|
|
const sourceXY = RegionalForecast.getXYFromLatitudeLongitude(weatherParameters.latitude, weatherParameters.longitude, offsetXY.x, offsetXY.y, weatherParameters.state);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// get latitude and longitude limits
|
2022-08-05 03:12:08 +00:00
|
|
|
const minMaxLatLon = RegionalForecast.getMinMaxLatitudeLongitude(sourceXY.x, sourceXY.y, offsetXY.x, offsetXY.y, weatherParameters.state);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// get a target distance
|
|
|
|
let targetDistance = 2.5;
|
2020-10-16 20:30:27 +00:00
|
|
|
if (weatherParameters.state === 'HI') targetDistance = 1;
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// make station info into an array
|
2020-10-29 21:44:28 +00:00
|
|
|
const stationInfoArray = Object.values(StationInfo).map((value) => ({ ...value, targetDistance }));
|
2020-09-08 15:23:18 +00:00
|
|
|
// combine regional cities with station info for additional stations
|
|
|
|
// stations are intentionally after cities to allow cities priority when drawing the map
|
2020-10-29 21:44:28 +00:00
|
|
|
const combinedCities = [...RegionalCities, ...stationInfoArray];
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// Determine which cities are within the max/min latitude/longitude.
|
|
|
|
const regionalCities = [];
|
2020-10-29 21:44:28 +00:00
|
|
|
combinedCities.forEach((city) => {
|
|
|
|
if (city.lat > minMaxLatLon.minLat && city.lat < minMaxLatLon.maxLat
|
|
|
|
&& city.lon > minMaxLatLon.minLon && city.lon < minMaxLatLon.maxLon - 1) {
|
|
|
|
// default to 1 for cities loaded from RegionalCities, use value calculate above for remaining stations
|
|
|
|
const targetDist = city.targetDistance || 1;
|
2020-09-08 15:23:18 +00:00
|
|
|
// Only add the city as long as it isn't within set distance degree of any other city already in the array.
|
|
|
|
const okToAddCity = regionalCities.reduce((acc, testCity) => {
|
2020-09-25 20:11:19 +00:00
|
|
|
const distance = utils.calc.distance(city.lon, city.lat, testCity.lon, testCity.lat);
|
2020-10-29 21:44:28 +00:00
|
|
|
return acc && distance >= targetDist;
|
2020-09-08 15:23:18 +00:00
|
|
|
}, true);
|
|
|
|
if (okToAddCity) regionalCities.push(city);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// get regional forecasts and observations (the two are intertwined due to the design of api.weather.gov)
|
2022-08-05 03:26:09 +00:00
|
|
|
const regionalDataAll = await Promise.all(regionalCities.map(async (city) => {
|
2020-09-08 15:23:18 +00:00
|
|
|
try {
|
2022-11-22 20:17:04 +00:00
|
|
|
if (!city.point) throw new Error('No pre-loaded point');
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// start off the observation task
|
2022-11-22 20:17:04 +00:00
|
|
|
const observationPromise = RegionalForecast.getRegionalObservation(city.point, city);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
2022-11-22 20:17:04 +00:00
|
|
|
const forecast = await utils.fetch.json(`https://api.weather.gov/gridpoints/${city.point.wfo}/${city.point.x},${city.point.y}/forecast`);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// get XY on map for city
|
2022-08-05 03:12:08 +00:00
|
|
|
const cityXY = RegionalForecast.getXYForCity(city, minMaxLatLon.maxLat, minMaxLatLon.minLon, weatherParameters.state);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// wait for the regional observation if it's not done yet
|
|
|
|
const observation = await observationPromise;
|
|
|
|
// format the observation the same as the forecast
|
|
|
|
const regionalObservation = {
|
|
|
|
daytime: !!observation.icon.match(/\/day\//),
|
|
|
|
temperature: utils.units.celsiusToFahrenheit(observation.temperature.value),
|
2020-10-29 21:44:28 +00:00
|
|
|
name: RegionalForecast.formatCity(city.city),
|
2020-09-08 15:23:18 +00:00
|
|
|
icon: observation.icon,
|
|
|
|
x: cityXY.x,
|
|
|
|
y: cityXY.y,
|
|
|
|
};
|
|
|
|
|
2020-09-23 16:49:15 +00:00
|
|
|
// preload the icon
|
2020-09-26 04:07:13 +00:00
|
|
|
utils.image.preload(icons.getWeatherRegionalIconFromIconLink(regionalObservation.icon, !regionalObservation.daytime));
|
2020-09-23 16:49:15 +00:00
|
|
|
|
2020-09-08 15:23:18 +00:00
|
|
|
// return a pared-down forecast
|
|
|
|
// 0th object is the current conditions
|
|
|
|
// first object is the next period i.e. if it's daytime then it's the "tonight" forecast
|
|
|
|
// second object is the following period
|
|
|
|
// always skip the first forecast index because it's what's going on right now
|
|
|
|
return [
|
|
|
|
regionalObservation,
|
2020-10-29 21:44:28 +00:00
|
|
|
RegionalForecast.buildForecast(forecast.properties.periods[1], city, cityXY),
|
|
|
|
RegionalForecast.buildForecast(forecast.properties.periods[2], city, cityXY),
|
2020-09-08 15:23:18 +00:00
|
|
|
];
|
|
|
|
} catch (e) {
|
2022-11-22 03:50:22 +00:00
|
|
|
console.log(`No regional forecast data for '${city.name ?? city.city}'`);
|
2020-10-02 02:35:49 +00:00
|
|
|
console.log(e);
|
2020-09-08 15:23:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-08-05 03:26:09 +00:00
|
|
|
}));
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// filter out any false (unavailable data)
|
2020-10-29 21:44:28 +00:00
|
|
|
const regionalData = regionalDataAll.filter((data) => data);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
2020-09-09 20:23:19 +00:00
|
|
|
// test for data present
|
|
|
|
if (regionalData.length === 0) {
|
|
|
|
this.setStatus(STATUS.noData);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-08 15:23:18 +00:00
|
|
|
// return the weather data and offsets
|
|
|
|
this.data = {
|
|
|
|
regionalData,
|
|
|
|
offsetXY,
|
|
|
|
sourceXY,
|
|
|
|
};
|
|
|
|
|
|
|
|
this.setStatus(STATUS.loaded);
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static buildForecast(forecast, city, cityXY) {
|
2020-09-08 15:23:18 +00:00
|
|
|
return {
|
|
|
|
daytime: forecast.isDaytime,
|
2020-10-29 21:44:28 +00:00
|
|
|
temperature: forecast.temperature || 0,
|
|
|
|
name: RegionalForecast.formatCity(city.city),
|
2020-09-08 15:23:18 +00:00
|
|
|
icon: forecast.icon,
|
|
|
|
x: cityXY.x,
|
|
|
|
y: cityXY.y,
|
2020-09-17 01:55:34 +00:00
|
|
|
time: forecast.startTime,
|
2020-09-08 15:23:18 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static async getRegionalObservation(point, city) {
|
2020-09-08 15:23:18 +00:00
|
|
|
try {
|
|
|
|
// get stations
|
2022-11-22 20:17:04 +00:00
|
|
|
const stations = await utils.fetch.json(`https://api.weather.gov/gridpoints/${city.point.wfo}/${city.point.x},${city.point.y}/stations`);
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
// get the first station
|
|
|
|
const station = stations.features[0].id;
|
|
|
|
// get the observation data
|
2020-10-02 02:35:49 +00:00
|
|
|
const observation = await utils.fetch.json(`${station}/observations/latest`);
|
2020-09-23 16:49:15 +00:00
|
|
|
// preload the image
|
2022-11-22 03:50:22 +00:00
|
|
|
if (!observation.properties.icon) return false;
|
2020-09-23 16:49:15 +00:00
|
|
|
utils.image.preload(icons.getWeatherRegionalIconFromIconLink(observation.properties.icon, !observation.properties.daytime));
|
2020-09-08 15:23:18 +00:00
|
|
|
// return the observation
|
|
|
|
return observation.properties;
|
|
|
|
} catch (e) {
|
2022-11-22 03:50:22 +00:00
|
|
|
console.log(`Unable to get regional observations for ${city.Name ?? city.city}`);
|
2020-09-23 16:49:15 +00:00
|
|
|
console.error(e.status, e.responseJSON);
|
2020-09-08 15:23:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// utility latitude/pixel conversions
|
2022-08-05 03:12:08 +00:00
|
|
|
static getXYFromLatitudeLongitude(Latitude, Longitude, OffsetX, OffsetY, state) {
|
|
|
|
if (state === 'AK') return RegionalForecast.getXYFromLatitudeLongitudeAK(Latitude, Longitude, OffsetX, OffsetY);
|
|
|
|
if (state === 'HI') return RegionalForecast.getXYFromLatitudeLongitudeHI(Latitude, Longitude, OffsetX, OffsetY);
|
2020-09-08 15:23:18 +00:00
|
|
|
let y = 0;
|
|
|
|
let x = 0;
|
|
|
|
const ImgHeight = 1600;
|
|
|
|
const ImgWidth = 2550;
|
|
|
|
|
|
|
|
y = (50.5 - Latitude) * 55.2;
|
|
|
|
y -= OffsetY; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (y > (ImgHeight - (OffsetY * 2))) {
|
|
|
|
y = ImgHeight - (OffsetY * 2);
|
|
|
|
} else if (y < 0) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = ((-127.5 - Longitude) * 41.775) * -1;
|
|
|
|
x -= OffsetX; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (x > (ImgWidth - (OffsetX * 2))) {
|
|
|
|
x = ImgWidth - (OffsetX * 2);
|
|
|
|
} else if (x < 0) {
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getXYFromLatitudeLongitudeAK(Latitude, Longitude, OffsetX, OffsetY) {
|
2020-09-08 15:23:18 +00:00
|
|
|
let y = 0;
|
|
|
|
let x = 0;
|
|
|
|
const ImgHeight = 1142;
|
|
|
|
const ImgWidth = 1200;
|
|
|
|
|
|
|
|
y = (73.0 - Latitude) * 56;
|
|
|
|
y -= OffsetY; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (y > (ImgHeight - (OffsetY * 2))) {
|
|
|
|
y = ImgHeight - (OffsetY * 2);
|
|
|
|
} else if (y < 0) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = ((-175.0 - Longitude) * 25.0) * -1;
|
|
|
|
x -= OffsetX; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (x > (ImgWidth - (OffsetX * 2))) {
|
|
|
|
x = ImgWidth - (OffsetX * 2);
|
|
|
|
} else if (x < 0) {
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getXYFromLatitudeLongitudeHI(Latitude, Longitude, OffsetX, OffsetY) {
|
2020-09-08 15:23:18 +00:00
|
|
|
let y = 0;
|
|
|
|
let x = 0;
|
|
|
|
const ImgHeight = 571;
|
|
|
|
const ImgWidth = 600;
|
|
|
|
|
|
|
|
y = (25 - Latitude) * 55.2;
|
|
|
|
y -= OffsetY; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (y > (ImgHeight - (OffsetY * 2))) {
|
|
|
|
y = ImgHeight - (OffsetY * 2);
|
|
|
|
} else if (y < 0) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = ((-164.5 - Longitude) * 41.775) * -1;
|
|
|
|
x -= OffsetX; // Centers map.
|
|
|
|
// Do not allow the map to exceed the max/min coordinates.
|
|
|
|
if (x > (ImgWidth - (OffsetX * 2))) {
|
|
|
|
x = ImgWidth - (OffsetX * 2);
|
|
|
|
} else if (x < 0) {
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2022-08-05 03:12:08 +00:00
|
|
|
static getMinMaxLatitudeLongitude(X, Y, OffsetX, OffsetY, state) {
|
|
|
|
if (state === 'AK') return RegionalForecast.getMinMaxLatitudeLongitudeAK(X, Y, OffsetX, OffsetY);
|
|
|
|
if (state === 'HI') return RegionalForecast.getMinMaxLatitudeLongitudeHI(X, Y, OffsetX, OffsetY);
|
2020-09-08 15:23:18 +00:00
|
|
|
const maxLat = ((Y / 55.2) - 50.5) * -1;
|
|
|
|
const minLat = (((Y + (OffsetY * 2)) / 55.2) - 50.5) * -1;
|
|
|
|
const minLon = (((X * -1) / 41.775) + 127.5) * -1;
|
|
|
|
const maxLon = ((((X + (OffsetX * 2)) * -1) / 41.775) + 127.5) * -1;
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
return {
|
|
|
|
minLat, maxLat, minLon, maxLon,
|
|
|
|
};
|
2020-09-08 15:23:18 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getMinMaxLatitudeLongitudeAK(X, Y, OffsetX, OffsetY) {
|
2020-09-08 15:23:18 +00:00
|
|
|
const maxLat = ((Y / 56) - 73.0) * -1;
|
|
|
|
const minLat = (((Y + (OffsetY * 2)) / 56) - 73.0) * -1;
|
|
|
|
const minLon = (((X * -1) / 25) + 175.0) * -1;
|
|
|
|
const maxLon = ((((X + (OffsetX * 2)) * -1) / 25) + 175.0) * -1;
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
return {
|
|
|
|
minLat, maxLat, minLon, maxLon,
|
|
|
|
};
|
2020-09-08 15:23:18 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getMinMaxLatitudeLongitudeHI(X, Y, OffsetX, OffsetY) {
|
2020-09-08 15:23:18 +00:00
|
|
|
const maxLat = ((Y / 55.2) - 25) * -1;
|
|
|
|
const minLat = (((Y + (OffsetY * 2)) / 55.2) - 25) * -1;
|
|
|
|
const minLon = (((X * -1) / 41.775) + 164.5) * -1;
|
|
|
|
const maxLon = ((((X + (OffsetX * 2)) * -1) / 41.775) + 164.5) * -1;
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
return {
|
|
|
|
minLat, maxLat, minLon, maxLon,
|
|
|
|
};
|
2020-09-08 15:23:18 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 03:12:08 +00:00
|
|
|
static getXYForCity(City, MaxLatitude, MinLongitude, state) {
|
|
|
|
if (state === 'AK') RegionalForecast.getXYForCityAK(City, MaxLatitude, MinLongitude);
|
|
|
|
if (state === 'HI') RegionalForecast.getXYForCityHI(City, MaxLatitude, MinLongitude);
|
2020-09-25 20:11:19 +00:00
|
|
|
let x = (City.lon - MinLongitude) * 57;
|
|
|
|
let y = (MaxLatitude - City.lat) * 70;
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
if (y < 30) y = 30;
|
|
|
|
if (y > 282) y = 282;
|
|
|
|
|
|
|
|
if (x < 40) x = 40;
|
|
|
|
if (x > 580) x = 580;
|
|
|
|
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getXYForCityAK(City, MaxLatitude, MinLongitude) {
|
2020-09-25 20:11:19 +00:00
|
|
|
let x = (City.lon - MinLongitude) * 37;
|
|
|
|
let y = (MaxLatitude - City.lat) * 70;
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
if (y < 30) y = 30;
|
|
|
|
if (y > 282) y = 282;
|
|
|
|
|
|
|
|
if (x < 40) x = 40;
|
|
|
|
if (x > 580) x = 580;
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
static getXYForCityHI(City, MaxLatitude, MinLongitude) {
|
2020-09-25 20:11:19 +00:00
|
|
|
let x = (City.lon - MinLongitude) * 57;
|
|
|
|
let y = (MaxLatitude - City.lat) * 70;
|
2020-09-08 15:23:18 +00:00
|
|
|
|
|
|
|
if (y < 30) y = 30;
|
|
|
|
if (y > 282) y = 282;
|
|
|
|
|
|
|
|
if (x < 40) x = 40;
|
|
|
|
if (x > 580) x = 580;
|
|
|
|
|
|
|
|
return { x, y };
|
|
|
|
}
|
|
|
|
|
2020-09-25 20:11:19 +00:00
|
|
|
// to fit on the map, remove anything after punctuation and then limit to 15 characters
|
2020-10-29 21:44:28 +00:00
|
|
|
static formatCity(city) {
|
|
|
|
return city.match(/[^-;/\\,]*/)[0].substr(0, 12);
|
2020-09-25 20:11:19 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 03:26:09 +00:00
|
|
|
drawCanvas() {
|
2020-09-04 18:02:20 +00:00
|
|
|
super.drawCanvas();
|
|
|
|
// break up data into useful values
|
2020-10-29 21:44:28 +00:00
|
|
|
const { regionalData: data, sourceXY, offsetXY } = this.data;
|
2020-09-04 18:02:20 +00:00
|
|
|
|
2020-10-29 21:44:28 +00:00
|
|
|
const { DateTime } = luxon;
|
2020-09-04 18:02:20 +00:00
|
|
|
// draw the header graphics
|
|
|
|
|
|
|
|
// draw the appropriate title
|
2022-08-05 01:12:44 +00:00
|
|
|
const titleTop = this.elem.querySelector('.title.dual .top');
|
|
|
|
const titleBottom = this.elem.querySelector('.title.dual .bottom');
|
2020-09-08 15:23:18 +00:00
|
|
|
if (this.screenIndex === 0) {
|
2022-08-05 01:12:44 +00:00
|
|
|
titleTop.innerHTML = 'Regional';
|
|
|
|
titleBottom.innerHTML = 'Observations';
|
2020-09-04 18:02:20 +00:00
|
|
|
} else {
|
2020-10-29 21:44:28 +00:00
|
|
|
const forecastDate = DateTime.fromISO(data[0][this.screenIndex].time);
|
2020-09-04 18:02:20 +00:00
|
|
|
|
|
|
|
// get the name of the day
|
2020-10-29 21:44:28 +00:00
|
|
|
const dayName = forecastDate.toLocaleString({ weekday: 'long' });
|
2022-08-05 01:12:44 +00:00
|
|
|
titleTop.innerHTML = 'Forecast for';
|
2020-09-04 18:02:20 +00:00
|
|
|
// draw the title
|
2020-09-08 15:23:18 +00:00
|
|
|
if (data[0][this.screenIndex].daytime) {
|
2022-08-05 01:12:44 +00:00
|
|
|
titleBottom.innerHTML = dayName;
|
2020-09-04 18:02:20 +00:00
|
|
|
} else {
|
2022-08-05 01:12:44 +00:00
|
|
|
titleBottom.innerHTML = `${dayName} Night`;
|
2020-09-04 18:02:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw the map
|
2022-08-04 21:30:13 +00:00
|
|
|
const scale = 640 / (offsetXY.x * 2);
|
|
|
|
const map = this.elem.querySelector('.map');
|
|
|
|
map.style.zoom = scale;
|
|
|
|
map.style.top = `-${sourceXY.y}px`;
|
|
|
|
map.style.left = `-${sourceXY.x}px`;
|
|
|
|
|
|
|
|
const cities = data.map((city) => {
|
|
|
|
const fill = {};
|
|
|
|
const period = city[this.screenIndex];
|
|
|
|
|
|
|
|
fill.icon = { type: 'img', src: icons.getWeatherRegionalIconFromIconLink(period.icon, !period.daytime) };
|
|
|
|
fill.city = period.name;
|
|
|
|
let { temperature } = period;
|
|
|
|
if (navigation.units() === UNITS.metric) temperature = Math.round(utils.units.fahrenheitToCelsius(temperature));
|
|
|
|
fill.temp = temperature;
|
|
|
|
|
|
|
|
const elem = this.fillTemplate('location', fill);
|
|
|
|
elem.style.left = `${period.x}px`;
|
|
|
|
elem.style.top = `${period.y}px`;
|
|
|
|
|
|
|
|
return elem;
|
|
|
|
});
|
|
|
|
|
|
|
|
const locationContainer = this.elem.querySelector('.location-container');
|
|
|
|
locationContainer.innerHTML = '';
|
|
|
|
locationContainer.append(...cities);
|
|
|
|
|
2020-09-04 18:02:20 +00:00
|
|
|
this.finishDraw();
|
|
|
|
}
|
2020-10-29 21:44:28 +00:00
|
|
|
}
|