From 44d43cc56f43dd282e4536da0c88d96e3ef5c406 Mon Sep 17 00:00:00 2001 From: Jin Igarashi Date: Fri, 9 Aug 2024 23:55:31 +0100 Subject: [PATCH] fix: improved algorithm to get the correct time's sky definition. update sky when move map if location is not specified. (#10) --- .changeset/witty-wombats-doubt.md | 5 ++ packages/maplibre-gl-sky/README.md | 8 +- packages/maplibre-gl-sky/index.html | 2 +- packages/maplibre-gl-sky/index.ts | 3 + .../maplibre-gl-sky/src/lib/SkyControl.ts | 79 ++++++++++++++----- .../src/lib/{ => constants}/defaultOptions.ts | 2 +- .../src/lib/constants/index.ts | 1 + packages/maplibre-gl-sky/src/lib/index.ts | 1 + 8 files changed, 75 insertions(+), 26 deletions(-) create mode 100644 .changeset/witty-wombats-doubt.md rename packages/maplibre-gl-sky/src/lib/{ => constants}/defaultOptions.ts (98%) create mode 100644 packages/maplibre-gl-sky/src/lib/constants/index.ts diff --git a/.changeset/witty-wombats-doubt.md b/.changeset/witty-wombats-doubt.md new file mode 100644 index 0000000..a9b5f10 --- /dev/null +++ b/.changeset/witty-wombats-doubt.md @@ -0,0 +1,5 @@ +--- +"@watergis/maplibre-gl-sky": patch +--- + +fix: improved algorithm to get the correct time's sky definition. update sky when move map if location is not specified. diff --git a/packages/maplibre-gl-sky/README.md b/packages/maplibre-gl-sky/README.md index b18c19a..20dd891 100644 --- a/packages/maplibre-gl-sky/README.md +++ b/packages/maplibre-gl-sky/README.md @@ -21,14 +21,14 @@ import { SkyControl } from '@watergis/maplibre-gl-sky'; const map = new Map(); const sky = new SkyControl(); -sky.addToMap(map); +sky.addTo(map); ``` - add specific sky color ```ts const sky = new SkyControl(); -sky.addToMap(map, { +sky.addTo(map, { timeType: 'sunset' }); ``` @@ -37,7 +37,7 @@ sky.addToMap(map, { ```ts const sky = new SkyControl(); -sky.addToMap(map, { +sky.addTo(map, { date: new Date() }); ``` @@ -51,7 +51,7 @@ const newOptions = defaultSkyOptions; // edit your options for `newOptions` const sky = new SkyControl(newOptions); -sky.addToMap(map); +sky.addTo(map); ``` ## License diff --git a/packages/maplibre-gl-sky/index.html b/packages/maplibre-gl-sky/index.html index f3697c3..71b1712 100644 --- a/packages/maplibre-gl-sky/index.html +++ b/packages/maplibre-gl-sky/index.html @@ -40,7 +40,7 @@ >
-

+

diff --git a/packages/maplibre-gl-sky/index.ts b/packages/maplibre-gl-sky/index.ts index 69a1046..5cb4249 100644 --- a/packages/maplibre-gl-sky/index.ts +++ b/packages/maplibre-gl-sky/index.ts @@ -65,6 +65,9 @@ const map = new Map({ map.addControl(new NavigationControl({ visualizePitch: true }), 'top-right'); map.addControl(new maplibregl.AttributionControl({ compact: false }), 'bottom-right'); +const sky = new SkyControl(); +sky.addTo(map); + const timeButtons = document.getElementById('time-buttons'); const autoBtn = document.createElement('button'); diff --git a/packages/maplibre-gl-sky/src/lib/SkyControl.ts b/packages/maplibre-gl-sky/src/lib/SkyControl.ts index b8da644..5eb20f5 100644 --- a/packages/maplibre-gl-sky/src/lib/SkyControl.ts +++ b/packages/maplibre-gl-sky/src/lib/SkyControl.ts @@ -1,8 +1,10 @@ import { Map, SkySpecification } from 'maplibre-gl'; import SunCalc from 'suncalc'; -import { AddToOptions, AvailableTimeTypes, Options, SkyTimeType } from './interfaces'; -import { defaultSkyOptions } from './defaultOptions'; +import { AddToOptions, AvailableTimeTypes, Options, SkyTimeType, TimeType } from './interfaces'; +import { defaultSkyOptions } from './constants'; import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +dayjs.extend(utc); export class SkyControl { private map?: Map; @@ -29,10 +31,14 @@ export class SkyControl { this.map?.setSky(currentSky); }); } - } - private timeToSec(date: dayjs.Dayjs) { - return date.hour() * 60 * 60 + date.minute() * 60 + date.second(); + if (!options?.location) { + this.map.on('moveend', () => { + const currentSky = this.getSky(options); + if (!currentSky) return; + this.map?.setSky(currentSky); + }); + } } private getSky(options?: AddToOptions) { @@ -62,24 +68,40 @@ export class SkyControl { private getSkySpecByTime(lng: number, lat: number, date?: Date) { const skyOptions = this.options.skyOptions; if (!skyOptions) return; + // convert to UTC + let currentDate: dayjs.Dayjs; if (!date) { - date = new Date(); + currentDate = dayjs.utc(); + } else { + currentDate = dayjs(date).utc(); } - const times = SunCalc.getTimes(date, lng, lat); + const times = SunCalc.getTimes(currentDate.toDate(), lat, lng); - const currentDate = dayjs(date); - const currentTimeSec = this.timeToSec(currentDate); + // add 1 day before and 1 day after + const timesBefore: { type: TimeType; date: dayjs.Dayjs }[] = []; + const timesToday: { type: TimeType; date: dayjs.Dayjs }[] = []; + const timesAfter: { type: TimeType; date: dayjs.Dayjs }[] = []; + AvailableTimeTypes.forEach((timeType) => { + const targetTime = dayjs(times[timeType]).utc(); + timesToday.push({ type: timeType, date: targetTime }); + const before = targetTime.add(-1, 'day'); + timesBefore.push({ type: timeType, date: before }); + + const after = targetTime.add(1, 'day'); + timesAfter.push({ type: timeType, date: after }); + }); + let availableTImes = [...timesBefore, ...timesToday, ...timesAfter]; + availableTImes = availableTImes.sort( + (a, b) => a.date.toDate().getTime() - b.date.toDate().getTime() + ); let beforeTime: SkyTimeType = {}; let afterTime: SkyTimeType = {}; - AvailableTimeTypes.forEach((timeType) => { - let targetTime = dayjs(times[timeType]); - let targetTimeSec = this.timeToSec(targetTime); - if (targetTime.isSame(currentDate, 'day') && targetTimeSec < currentTimeSec) { - targetTime = targetTime.add(-1, 'day'); - targetTimeSec = this.timeToSec(targetTime); - } + availableTImes.forEach((time) => { + const targetTime = time.date; + const timeType = time.type; + // console.log(timeType, targetTime.toISOString(), currentDate.toISOString()) if (targetTime.isBefore(currentDate)) { const sky = skyOptions[timeType] as SkySpecification; @@ -117,11 +139,28 @@ export class SkyControl { // console.log(beforeTime, afterTime); - const activeTime = afterTime?.sky ?? beforeTime?.sky; - if (activeTime) { - return activeTime as SkySpecification; + const beforeDiff = beforeTime.date + ? currentDate.toDate().getTime() - beforeTime.date.toDate().getTime() + : -1; + const afterDiff = afterTime.date + ? afterTime.date.toDate().getTime() - currentDate.toDate().getTime() + : -1; + + let activeTime: SkySpecification; + if (beforeDiff > -1 && afterDiff > -1) { + if (afterDiff > beforeDiff) { + activeTime = afterTime.sky as SkySpecification; + } else { + activeTime = beforeTime.sky as SkySpecification; + } + } else if (beforeTime && !afterTime) { + activeTime = beforeTime.sky as SkySpecification; + } else if (afterTime && !beforeTime) { + activeTime = afterTime.sky as SkySpecification; } else { - return skyOptions.solarNoon; + activeTime = skyOptions.solarNoon; } + + return activeTime; } } diff --git a/packages/maplibre-gl-sky/src/lib/defaultOptions.ts b/packages/maplibre-gl-sky/src/lib/constants/defaultOptions.ts similarity index 98% rename from packages/maplibre-gl-sky/src/lib/defaultOptions.ts rename to packages/maplibre-gl-sky/src/lib/constants/defaultOptions.ts index 513652e..23dc1d5 100644 --- a/packages/maplibre-gl-sky/src/lib/defaultOptions.ts +++ b/packages/maplibre-gl-sky/src/lib/constants/defaultOptions.ts @@ -1,4 +1,4 @@ -import { Options } from './interfaces'; +import { Options } from '../interfaces'; export const defaultSkyOptions: Options = { skyOptions: { diff --git a/packages/maplibre-gl-sky/src/lib/constants/index.ts b/packages/maplibre-gl-sky/src/lib/constants/index.ts new file mode 100644 index 0000000..3c2bf3c --- /dev/null +++ b/packages/maplibre-gl-sky/src/lib/constants/index.ts @@ -0,0 +1 @@ +export * from './defaultOptions'; diff --git a/packages/maplibre-gl-sky/src/lib/index.ts b/packages/maplibre-gl-sky/src/lib/index.ts index ed77ab8..edabd73 100644 --- a/packages/maplibre-gl-sky/src/lib/index.ts +++ b/packages/maplibre-gl-sky/src/lib/index.ts @@ -1,2 +1,3 @@ export * from './SkyControl'; export * from './interfaces'; +export * from './constants';