Show sunrise / sunset times in the planner.

* A ‘sun’ icon is shown when a line starts and ends in daytime
* A ‘moon’ icon is shown when a line starts and ends in nighttime
* A ‘sun/moon’ icon is shown in other cases

Sunrise and sunset times are provided as a tooltip when hovering over
the icon.

Closes #72.
This commit is contained in:
D. Berge
2021-05-27 01:02:42 +02:00
parent 7aecb514db
commit 7ead826677
3 changed files with 134 additions and 0 deletions

View File

@@ -17,6 +17,7 @@
"leaflet-realtime": "^2.2.0",
"leaflet.markercluster": "^1.4.1",
"marked": "^2.0.3",
"suncalc": "^1.8.0",
"typeface-roboto": "0.0.75",
"vue": "^2.6.12",
"vue-debounce": "^2.6.0",
@@ -10971,6 +10972,11 @@
"node": ">= 8"
}
},
"node_modules/suncalc": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.8.0.tgz",
"integrity": "sha1-HZiYEJVjB4dQ9JlKlZ5lTYdqy/U="
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -22341,6 +22347,11 @@
"when": "~3.6.x"
}
},
"suncalc": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.8.0.tgz",
"integrity": "sha1-HZiYEJVjB4dQ9JlKlZ5lTYdqy/U="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

View File

@@ -15,6 +15,7 @@
"leaflet-realtime": "^2.2.0",
"leaflet.markercluster": "^1.4.1",
"marked": "^2.0.3",
"suncalc": "^1.8.0",
"typeface-roboto": "0.0.75",
"vue": "^2.6.12",
"vue-debounce": "^2.6.0",

View File

@@ -44,6 +44,10 @@
@contextmenu:row="contextMenu"
>
<template v-slot:item.srss="{item}">
<v-icon small :title="srssInfo(item)">{{srssIcon(item)}}</v-icon>
</template>
<template v-slot:item.sequence="{item, value}">
<v-edit-dialog
large
@@ -247,6 +251,7 @@
</style>
<script>
import suncalc from 'suncalc';
import { mapActions, mapGetters } from 'vuex';
export default {
@@ -262,6 +267,10 @@ export default {
value: "sequence",
text: "Sequence"
},
{
value: "srss",
text: "SR/SS"
},
{
value: "name",
text: "Name"
@@ -415,6 +424,119 @@ export default {
},
methods: {
suntimes (line) {
const oneday = 86400000;
function isDay (srss, ts, lat, lng) {
if (isNaN(srss.sunriseEnd) || isNaN(srss.sunsetStart)) {
// Between March and September
if (ts.getMonth() >= 2 && ts.getMonth() <= 8) {
// Polar day in the Northern hemisphere, night in the South
return lat > 0;
} else {
return lat < 0;
}
} else {
if (srss.sunriseEnd < ts) {
if (ts < srss.sunsetStart) {
return true;
} else {
return suncalc.getTimes(new Date(ts.valueOf() + oneday), lat, lng).sunriseEnd < ts;
}
} else {
return ts < suncalc.getTimes(new Date(ts.valueOf() - oneday), lat, lng).sunsetStart;
}
}
}
let {ts0, ts1} = line;
const [ lng0, lat0 ] = line.geometry.coordinates[0];
const [ lng1, lat1 ] = line.geometry.coordinates[1];
if (ts1-ts0 > oneday) {
console.warn("Cannot provide reliable sunrise / sunset times for lines over 24 hr in this version");
//return null;
}
const srss0 = suncalc.getTimes(ts0, lat0, lng0);
const srss1 = suncalc.getTimes(ts1, lat1, lng1);
srss0.prevDay = suncalc.getTimes(new Date(ts0.valueOf()-oneday), lat0, lng0);
srss1.nextDay = suncalc.getTimes(new Date(ts1.valueOf()+oneday), lat1, lng1);
srss0.isDay = isDay(srss0, ts0, lat0, lng0);
srss1.isDay = isDay(srss1, ts1, lat1, lng1);
return {
ts0: srss0,
ts1: srss1
};
},
srssIcon (line) {
const srss = this.suntimes(line);
const moon = suncalc.getMoonIllumination(line.ts0);
return srss.ts0.isDay && srss.ts1.isDay
? 'mdi-weather-sunny'
: !srss.ts0.isDay && !srss.ts1.isDay
? moon.phase < 0.05
? 'mdi-moon-new'
: moon.phase < 0.25
? 'mdi-moon-waxing-crescent'
: moon.phase < 0.45
? 'mdi-moon-waxing-gibbous'
: moon.phase < 0.55
? 'mdi-moon-full'
: moon.phase < 0.75
? 'mdi-moon-waning-gibbous'
: 'mdi-moon-waning-crescent'
: 'mdi-theme-light-dark';
},
srssMoonPhase (line) {
const ts = new Date((Number(line.ts0)+Number(line.ts1))/2);
const moon = suncalc.getMoonIllumination(ts);
return moon.phase < 0.05
? 'New moon'
: moon.phase < 0.25
? 'Waxing crescent moon'
: moon.phase < 0.45
? 'Waxing gibbous moon'
: moon.phase < 0.55
? 'Full moon'
: moon.phase < 0.75
? 'Waning gibbous moon'
: 'Waning crescent moon';
},
srssInfo (line) {
const srss = this.suntimes(line);
const text = [];
try {
text.push(`Sunset at\t${srss.ts0.prevDay.sunsetStart.toISOString().substr(0, 16)}Z (FSP)`);
text.push(`Sunrise at\t${srss.ts0.sunriseEnd.toISOString().substr(0, 16)}Z (FSP)`);
text.push(`Sunset at\t${srss.ts0.sunsetStart.toISOString().substr(0, 16)}Z (FSP)`);
if (line.ts0.getUTCDate() != line.ts1.getUTCDate()) {
text.push(`Sunrise at\t${srss.ts1.sunriseEnd.toISOString().substr(0, 16)}Z (LSP)`);
text.push(`Sunset at\t${srss.ts1.sunsetStart.toISOString().substr(0, 16)}Z (LSP)`);
}
text.push(`Sunrise at\t${srss.ts1.nextDay.sunriseEnd.toISOString().substr(0, 16)}Z (LSP)`);
} catch (err) {
if (err instanceof RangeError) {
text.push(srss.ts0.isDay ? "Polar day" : "Polar night");
} else {
console.log("ERROR", err);
}
}
if (!srss.ts0.isDay || !srss.ts1.isDay) {
text.push(this.srssMoonPhase(line));
}
return text.join("\n");
},
lagAfter (item) {
const pos = this.items.indexOf(item)+1;