diff --git a/src/DesktopApp.vue b/src/DesktopApp.vue
index b3be8df6..03fff19f 100644
--- a/src/DesktopApp.vue
+++ b/src/DesktopApp.vue
@@ -29,7 +29,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts';
-import { loadMapAssets } from '@/lib/map/index.js';
+import { initMapProvider } from '@/lib/map/index.ts';
import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export default {
@@ -113,7 +113,7 @@ export default {
mounted() {
document.addEventListener('DOMContentLoaded', () => {
const languageInfo = this.$locale.getCurrentLanguageInfo();
- loadMapAssets(languageInfo ? languageInfo.alternativeLanguageTag : null);
+ initMapProvider(languageInfo ? languageInfo.alternativeLanguageTag : null);
});
}
}
diff --git a/src/MobileApp.vue b/src/MobileApp.vue
index fc35e649..746bd3fa 100644
--- a/src/MobileApp.vue
+++ b/src/MobileApp.vue
@@ -19,7 +19,7 @@ import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts';
import { getTheme, isEnableAnimate } from '@/lib/settings.ts';
-import { loadMapAssets } from '@/lib/map/index.js';
+import { initMapProvider } from '@/lib/map/index.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
import { isModalShowing, setAppFontSize } from '@/lib/ui/mobile.js';
@@ -194,7 +194,7 @@ export default {
document.addEventListener('DOMContentLoaded', () => {
const languageInfo = this.$locale.getCurrentLanguageInfo();
- loadMapAssets(languageInfo ? languageInfo.alternativeLanguageTag : null);
+ initMapProvider(languageInfo ? languageInfo.alternativeLanguageTag : null);
});
},
methods: {
diff --git a/src/components/common/MapView.vue b/src/components/common/MapView.vue
index bfb731cd..4f017724 100644
--- a/src/components/common/MapView.vue
+++ b/src/components/common/MapView.vue
@@ -8,112 +8,110 @@
v-if="!mapSupported || !mapDependencyLoaded">
-
diff --git a/src/consts/map.ts b/src/consts/map.ts
index b07150e6..d1454f42 100644
--- a/src/consts/map.ts
+++ b/src/consts/map.ts
@@ -1,23 +1,23 @@
-export interface PresetLeafletTileSource {
+export interface LeafletTileSource {
readonly tileUrlFormat: string;
readonly tileUrlSubDomains: string;
- readonly tileUrlExtraParams?: PresetLeafletTileSourceExtraParam[];
+ readonly tileUrlExtraParams?: LeafletTileSourceExtraParam[];
readonly annotationUrlFormat?: string;
readonly annotationUrlSubDomains?: string;
- readonly annotationUrlExtraParams?: PresetLeafletTileSourceExtraParam[];
+ readonly annotationUrlExtraParams?: LeafletTileSourceExtraParam[];
readonly minZoom: number;
readonly maxZoom: number;
readonly defaultZoomLevel: number;
- readonly website: string;
- readonly attribution: string;
+ readonly website?: string;
+ readonly attribution?: string;
}
-export interface PresetLeafletTileSourceExtraParam {
+export interface LeafletTileSourceExtraParam {
readonly paramName: string;
readonly paramValueType: string;
}
-export const LEAFLET_TILE_SOURCES: Record = {
+export const LEAFLET_TILE_SOURCES: Record = {
'openstreetmap': {
tileUrlFormat: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
tileUrlSubDomains: 'abc',
diff --git a/src/lib/map/amap.js b/src/lib/map/amap.js
deleted file mode 100644
index 65ce140f..00000000
--- a/src/lib/map/amap.js
+++ /dev/null
@@ -1,173 +0,0 @@
-import { asyncLoadAssets } from '@/lib/misc.ts';
-import services from '@/lib/services.js';
-import {
- getAmapSecurityVerificationMethod,
- getAmapApiExternalProxyUrl,
- getAmapApplicationSecret
-} from '@/lib/server_settings.ts';
-import logger from '@/lib/logger.ts';
-
-const amapHolder = {
- AMap: null
-};
-
-export function getAmapWebsite() {
- return 'https://www.amap.com';
-}
-
-export function loadAmapAssets() {
- if (amapHolder.AMap) {
- return;
- }
-
- if (!window._AMapSecurityConfig) {
- const amapSecurityConfig = {};
-
- if (getAmapSecurityVerificationMethod() === 'internalproxy') {
- amapSecurityConfig.serviceHost = services.generateAmapApiInternalProxyUrl();
- } else if (getAmapSecurityVerificationMethod() === 'externalproxy') {
- amapSecurityConfig.serviceHost = getAmapApiExternalProxyUrl();
- } else if (getAmapSecurityVerificationMethod() === 'plaintext') {
- amapSecurityConfig.securityJsCode = getAmapApplicationSecret();
- }
-
- window._AMapSecurityConfig = amapSecurityConfig;
- }
-
- if (!window.onAMapCallback) {
- window.onAMapCallback = () => {
- amapHolder.AMap = window.AMap;
- };
- }
-
- return asyncLoadAssets('js', services.generateAmapJavascriptUrl('onAMapCallback'));
-}
-
-export function createAmapHolder() {
- return {
- mapProvider: 'amap',
- dependencyLoaded: !!amapHolder.AMap,
- inited: false,
- defaultZoomLevel: 14,
- minZoomLevel: 1,
- amapInstance: null,
- amapToolbar: null,
- amapCenterPosition: null,
- amapCenterMarker: null
- };
-}
-
-export function createAmapInstance(mapHolder, mapContainer, options) {
- if (!amapHolder.AMap) {
- return null;
- }
-
- const AMap = amapHolder.AMap;
- const amapInstance = new AMap.Map(mapContainer, {
- zoom: options.zoomLevel,
- center: [ options.initCenter.longitude, options.initCenter.latitude ],
- zooms: [ 1, 19 ],
- jogEnable: false
- });
-
- const amapToolbar = new AMap.ToolBar({
- position: 'LT'
- });
- amapInstance.addControl(amapToolbar);
-
- mapHolder.amapInstance = amapInstance;
- mapHolder.amapToolbar = amapToolbar;
- mapHolder.inited = true;
-}
-
-export function setAmapCenterTo(mapHolder, center, zoomLevel) {
- if (!amapHolder.AMap || !mapHolder.amapInstance) {
- return;
- }
-
- const AMap = amapHolder.AMap;
-
- if (amapHolder.amapCenterPosition
- && amapHolder.amapCenterPosition.originalLongitude === center.longitude
- && amapHolder.amapCenterPosition.originalLatitude === center.latitude
- && amapHolder.amapCenterPosition.convertedLongitude
- && amapHolder.amapCenterPosition.convertedLatitude
- ) {
- mapHolder.amapInstance.setZoomAndCenter(zoomLevel, new AMap.LngLat(amapHolder.amapCenterPosition.convertedLongitude, amapHolder.amapCenterPosition.convertedLatitude));
- return;
- }
-
- amapHolder.amapCenterPosition = {
- originalLongitude: center.longitude,
- originalLatitude: center.latitude,
- convertedLongitude: null,
- convertedLatitude: null
- };
-
- const centerPoint = new AMap.LngLat(center.longitude, center.latitude);
-
- AMap.convertFrom(centerPoint, 'gps', (status, result) => {
- let convertedCenterPoint = centerPoint;
-
- if (result.info !== 'ok' || !result.locations) {
- logger.warn('amap geo position convert failed');
- } else {
- convertedCenterPoint = result.locations[0];
- amapHolder.amapCenterPosition.convertedLongitude = convertedCenterPoint.getLng();
- amapHolder.amapCenterPosition.convertedLatitude = convertedCenterPoint.getLat();
- }
-
- mapHolder.amapInstance.setZoomAndCenter(zoomLevel, convertedCenterPoint);
- });
-}
-
-export function setAmapCenterMaker(mapHolder, position) {
- if (!amapHolder.AMap || !mapHolder.amapInstance) {
- return;
- }
-
- const AMap = amapHolder.AMap;
- const setMaker = function (point) {
- if (!mapHolder.amapCenterMarker) {
- mapHolder.amapCenterMarker = new AMap.Marker({
- position: point
- });
- mapHolder.amapInstance.add(mapHolder.amapCenterMarker);
- } else {
- mapHolder.amapCenterMarker.setPosition(point);
- }
- }
-
- if (amapHolder.amapCenterPosition
- && amapHolder.amapCenterPosition.originalLongitude === position.longitude
- && amapHolder.amapCenterPosition.originalLatitude === position.latitude
- && amapHolder.amapCenterPosition.convertedLongitude
- && amapHolder.amapCenterPosition.convertedLatitude
- ) {
- setMaker(new AMap.LngLat(amapHolder.amapCenterPosition.convertedLongitude, amapHolder.amapCenterPosition.convertedLatitude));
- return;
- }
-
- const markerPoint = new AMap.LngLat(position.longitude, position.latitude);
-
- AMap.convertFrom(markerPoint, 'gps', (status, result) => {
- let convertedMarkPoint = markerPoint;
-
- if (result.info !== 'ok' || !result.locations) {
- logger.warn('amap geo position convert failed');
- } else {
- convertedMarkPoint = result.locations[0];
- }
-
- setMaker(convertedMarkPoint);
- });
-}
-
-export function removeAmapCenterMaker(mapHolder) {
- if (!mapHolder.amapInstance || !mapHolder.amapCenterMarker) {
- return;
- }
-
- mapHolder.amapInstance.remove(mapHolder.amapCenterMarker);
- mapHolder.amapCenterMarker = null;
-}
diff --git a/src/lib/map/amap.ts b/src/lib/map/amap.ts
new file mode 100644
index 00000000..4c96dfcb
--- /dev/null
+++ b/src/lib/map/amap.ts
@@ -0,0 +1,192 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
+
+import { asyncLoadAssets } from '@/lib/misc.ts';
+import services from '@/lib/services.js';
+import {
+ getAmapSecurityVerificationMethod,
+ getAmapApiExternalProxyUrl,
+ getAmapApplicationSecret
+} from '@/lib/server_settings.ts';
+import logger from '@/lib/logger.ts';
+
+export class AmapMapProvider implements MapProvider {
+ public static AMap: unknown = null;
+
+ public getWebsite(): string {
+ return 'https://www.amap.com';
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public asyncLoadAssets(language: string): Promise {
+ if (AmapMapProvider.AMap) {
+ return Promise.resolve();
+ }
+
+ if (!window._AMapSecurityConfig) {
+ const amapSecurityConfig = {};
+
+ if (getAmapSecurityVerificationMethod() === 'internalproxy') {
+ amapSecurityConfig.serviceHost = services.generateAmapApiInternalProxyUrl();
+ } else if (getAmapSecurityVerificationMethod() === 'externalproxy') {
+ amapSecurityConfig.serviceHost = getAmapApiExternalProxyUrl();
+ } else if (getAmapSecurityVerificationMethod() === 'plaintext') {
+ amapSecurityConfig.securityJsCode = getAmapApplicationSecret();
+ }
+
+ window._AMapSecurityConfig = amapSecurityConfig;
+ }
+
+ if (!window.onAMapCallback) {
+ window.onAMapCallback = () => {
+ AmapMapProvider.AMap = window.AMap;
+ };
+ }
+
+ return asyncLoadAssets('js', services.generateAmapJavascriptUrl('onAMapCallback'));
+ }
+
+ public createMapInstance(): MapInstance | null {
+ return new AmapMapInstance();
+ }
+}
+
+export class AmapMapInstance implements MapInstance {
+ public dependencyLoaded: boolean = false;
+ public inited: boolean = false;
+
+ public readonly defaultZoomLevel: number = 14;
+ public readonly minZoomLevel: number = 1;
+
+ private amapInstance: unknown = null;
+ private amapToolbar: unknown = null;
+ private amapCenterPosition: unknown = null;
+ private amapCenterMarker: unknown | null;
+
+ constructor() {
+ this.dependencyLoaded = !!AmapMapProvider.AMap;
+ }
+
+ public initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void {
+ if (!AmapMapProvider.AMap) {
+ return;
+ }
+
+ const AMap = AmapMapProvider.AMap;
+ const amapInstance = new AMap.Map(mapContainer, {
+ zoom: options.zoomLevel,
+ center: [ options.initCenter.longitude, options.initCenter.latitude ],
+ zooms: [ 1, 19 ],
+ jogEnable: false
+ });
+
+ const amapToolbar = new AMap.ToolBar({
+ position: 'LT'
+ });
+ amapInstance.addControl(amapToolbar);
+
+ this.amapInstance = amapInstance;
+ this.amapToolbar = amapToolbar;
+ this.inited = true;
+ }
+
+ public setMapCenterTo(center: MapPosition, zoomLevel: number): void {
+ if (!AmapMapProvider.AMap || !this.amapInstance) {
+ return;
+ }
+
+ const AMap = AmapMapProvider.AMap;
+
+ if (this.amapCenterPosition
+ && this.amapCenterPosition.originalLongitude === center.longitude
+ && this.amapCenterPosition.originalLatitude === center.latitude
+ && this.amapCenterPosition.convertedLongitude
+ && this.amapCenterPosition.convertedLatitude
+ ) {
+ this.amapInstance.setZoomAndCenter(zoomLevel, new AMap.LngLat(this.amapCenterPosition.convertedLongitude, this.amapCenterPosition.convertedLatitude));
+ return;
+ }
+
+ this.amapCenterPosition = {
+ originalLongitude: center.longitude,
+ originalLatitude: center.latitude,
+ convertedLongitude: null,
+ convertedLatitude: null
+ };
+
+ const centerPoint = new AMap.LngLat(center.longitude, center.latitude);
+
+ AMap.convertFrom(centerPoint, 'gps', (status, result) => {
+ let convertedCenterPoint = centerPoint;
+
+ if (result.info !== 'ok' || !result.locations) {
+ logger.warn('amap geo position convert failed');
+ } else {
+ convertedCenterPoint = result.locations[0];
+ this.amapCenterPosition.convertedLongitude = convertedCenterPoint.getLng();
+ this.amapCenterPosition.convertedLatitude = convertedCenterPoint.getLat();
+ }
+
+ this.amapInstance.setZoomAndCenter(zoomLevel, convertedCenterPoint);
+ });
+ }
+
+ public setMapCenterMarker(position: MapPosition): void {
+ if (!AmapMapProvider.AMap || !this.amapInstance) {
+ return;
+ }
+
+ const AMap = AmapMapProvider.AMap;
+
+ if (this.amapCenterPosition
+ && this.amapCenterPosition.originalLongitude === position.longitude
+ && this.amapCenterPosition.originalLatitude === position.latitude
+ && this.amapCenterPosition.convertedLongitude
+ && this.amapCenterPosition.convertedLatitude
+ ) {
+ this.setMaker(new AMap.LngLat(this.amapCenterPosition.convertedLongitude, this.amapCenterPosition.convertedLatitude));
+ return;
+ }
+
+ const markerPoint = new AMap.LngLat(position.longitude, position.latitude);
+
+ AMap.convertFrom(markerPoint, 'gps', (status, result) => {
+ let convertedMarkPoint = markerPoint;
+
+ if (result.info !== 'ok' || !result.locations) {
+ logger.warn('amap geo position convert failed');
+ } else {
+ convertedMarkPoint = result.locations[0];
+ }
+
+ this.setMaker(convertedMarkPoint);
+ });
+ }
+
+ public removeMapCenterMarker(): void {
+ if (!this.amapInstance || !this.amapCenterMarker) {
+ return;
+ }
+
+ this.amapInstance.remove(this.amapCenterMarker);
+ this.amapCenterMarker = null;
+ }
+
+ private setMaker(point: unknown): void {
+ if (!AmapMapProvider.AMap || !this.amapInstance) {
+ return;
+ }
+
+ const AMap = AmapMapProvider.AMap;
+
+ if (!this.amapCenterMarker) {
+ this.amapCenterMarker = new AMap.Marker({
+ position: point
+ });
+ this.amapInstance.add(this.amapCenterMarker);
+ } else {
+ this.amapCenterMarker.setPosition(point);
+ }
+ }
+}
diff --git a/src/lib/map/baidumap.js b/src/lib/map/baidumap.js
deleted file mode 100644
index 664ccfb3..00000000
--- a/src/lib/map/baidumap.js
+++ /dev/null
@@ -1,166 +0,0 @@
-import { asyncLoadAssets } from '@/lib/misc.ts';
-import services from '@/lib/services.js';
-import logger from '@/lib/logger.ts';
-
-const baiduMapHolder = {
- BMap: null,
- BMAP_NAVIGATION_CONTROL_ZOOM: window.BMAP_NAVIGATION_CONTROL_ZOOM || 3,
- BMAP_ANCHOR_TOP_LEFT: window.BMAP_ANCHOR_TOP_LEFT || 0,
- COORDINATES_WGS84: window.COORDINATES_WGS84 || 1,
- COORDINATES_BD09: window.COORDINATES_BD09 || 5
-};
-
-export function getBaiduMapWebsite() {
- return 'https://map.baidu.com';
-}
-
-export function loadBaiduMapAssets() {
- if (baiduMapHolder.BMap) {
- return;
- }
-
- if (!window.onBMapCallback) {
- window.onBMapCallback = () => {
- baiduMapHolder.BMap = window.BMap;
- };
- }
-
- return asyncLoadAssets('js', services.generateBaiduMapJavascriptUrl('onBMapCallback'));
-}
-
-export function createBaiduMapHolder() {
- return {
- mapProvider: 'baidumap',
- dependencyLoaded: !!baiduMapHolder.BMap,
- inited: false,
- defaultZoomLevel: 15,
- minZoomLevel: 1,
- baiduMapInstance: null,
- baiduMapConverter: null,
- baiduMapNavigationControl: null,
- baiduMapCenterPosition: null,
- baiduMapCenterMarker: null
- };
-}
-
-export function createBaiduMapInstance(mapHolder, mapContainer, options) {
- if (!baiduMapHolder.BMap) {
- return null;
- }
-
- const BMap = baiduMapHolder.BMap;
- const baiduMapInstance = new BMap.Map(mapContainer, {
- maxZoom: 19
- });
- baiduMapInstance.enableScrollWheelZoom();
-
- const baiduMapNavigationControl = new BMap.NavigationControl({
- type: baiduMapHolder.BMAP_NAVIGATION_CONTROL_ZOOM,
- anchor: baiduMapHolder.BMAP_ANCHOR_TOP_LEFT
- });
- baiduMapInstance.addControl(baiduMapNavigationControl);
- baiduMapInstance.centerAndZoom(new BMap.Point(options.initCenter.longitude, options.initCenter.latitude), options.zoomLevel);
-
- mapHolder.baiduMapInstance = baiduMapInstance;
- mapHolder.baiduMapConverter = new BMap.Convertor();
- mapHolder.baiduMapNavigationControl = baiduMapNavigationControl;
- mapHolder.inited = true;
-}
-
-export function setBaiduMapCenterTo(mapHolder, center, zoomLevel) {
- if (!baiduMapHolder.BMap || !mapHolder.baiduMapInstance) {
- return;
- }
-
- const BMap = baiduMapHolder.BMap;
-
- if (baiduMapHolder.baiduMapCenterPosition
- && baiduMapHolder.baiduMapCenterPosition.originalLongitude === center.longitude
- && baiduMapHolder.baiduMapCenterPosition.originalLatitude === center.latitude
- && baiduMapHolder.baiduMapCenterPosition.convertedLongitude
- && baiduMapHolder.baiduMapCenterPosition.convertedLatitude
- ) {
- mapHolder.baiduMapInstance.centerAndZoom(new BMap.Point(baiduMapHolder.baiduMapCenterPosition.convertedLongitude, baiduMapHolder.baiduMapCenterPosition.convertedLatitude), zoomLevel);
- return;
- }
-
- baiduMapHolder.baiduMapCenterPosition = {
- originalLongitude: center.longitude,
- originalLatitude: center.latitude,
- convertedLongitude: null,
- convertedLatitude: null
- };
-
- const centerPoint = new BMap.Point(center.longitude, center.latitude);
-
- if (mapHolder.baiduMapConverter) {
- mapHolder.baiduMapConverter.translate([ centerPoint ], baiduMapHolder.COORDINATES_WGS84, baiduMapHolder.COORDINATES_BD09, data => {
- let convertedCenterPoint = centerPoint;
-
- if (data.status !== 0 || !data.points) {
- logger.warn('baidu map geo position convert failed');
- } else {
- convertedCenterPoint = data.points[0];
- baiduMapHolder.baiduMapCenterPosition.convertedLongitude = convertedCenterPoint.lng;
- baiduMapHolder.baiduMapCenterPosition.convertedLatitude = convertedCenterPoint.lat;
- }
-
- mapHolder.baiduMapInstance.centerAndZoom(convertedCenterPoint, zoomLevel);
- });
- } else {
- mapHolder.baiduMapInstance.centerAndZoom(centerPoint, zoomLevel);
- }
-}
-
-export function setBaiduMapCenterMaker(mapHolder, position) {
- if (!baiduMapHolder.BMap || !mapHolder.baiduMapInstance) {
- return;
- }
-
- const BMap = baiduMapHolder.BMap;
- const setMaker = function (point) {
- if (!mapHolder.baiduMapCenterMarker) {
- mapHolder.baiduMapCenterMarker = new BMap.Marker(point);
- mapHolder.baiduMapInstance.addOverlay(mapHolder.baiduMapCenterMarker);
- } else {
- mapHolder.baiduMapCenterMarker.setPosition(point);
- }
- }
-
- if (baiduMapHolder.baiduMapCenterPosition
- && baiduMapHolder.baiduMapCenterPosition.originalLongitude === position.longitude
- && baiduMapHolder.baiduMapCenterPosition.originalLatitude === position.latitude
- && baiduMapHolder.baiduMapCenterPosition.convertedLongitude
- && baiduMapHolder.baiduMapCenterPosition.convertedLatitude
- ) {
- setMaker(new BMap.Point(baiduMapHolder.baiduMapCenterPosition.convertedLongitude, baiduMapHolder.baiduMapCenterPosition.convertedLatitude));
- return;
- }
-
- const markerPoint = new BMap.Point(position.longitude, position.latitude);
-
- if (mapHolder.baiduMapConverter) {
- mapHolder.baiduMapConverter.translate([ markerPoint ], baiduMapHolder.COORDINATES_WGS84, baiduMapHolder.COORDINATES_BD09, data => {
- let convertedMarkPoint = markerPoint;
-
- if (data.status !== 0 || !data.points) {
- logger.warn('baidu map geo position convert failed');
- } else {
- convertedMarkPoint = data.points[0];
- }
-
- setMaker(convertedMarkPoint);
- });
- } else {
- setMaker(markerPoint);
- }
-}
-
-export function removeBaiduMapCenterMaker(mapHolder) {
- if (!mapHolder.baiduMapInstance || !mapHolder.baiduMapCenterMarker) {
- return;
- }
-
- mapHolder.baiduMapInstance.removeOverlay(mapHolder.baiduMapCenterMarker);
- mapHolder.baiduMapCenterMarker = null;
-}
diff --git a/src/lib/map/baidumap.ts b/src/lib/map/baidumap.ts
new file mode 100644
index 00000000..35209839
--- /dev/null
+++ b/src/lib/map/baidumap.ts
@@ -0,0 +1,189 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
+
+import { asyncLoadAssets } from '@/lib/misc.ts';
+import services from '@/lib/services.js';
+import logger from '@/lib/logger.ts';
+
+export class BaiduMapProvider implements MapProvider {
+ public static BMap: unknown = null;
+ public static BMAP_NAVIGATION_CONTROL_ZOOM: unknown = window.BMAP_NAVIGATION_CONTROL_ZOOM || 3;
+ public static BMAP_ANCHOR_TOP_LEFT: unknown = window.BMAP_ANCHOR_TOP_LEFT || 0;
+ public static COORDINATES_WGS84: unknown = window.COORDINATES_WGS84 || 1;
+ public static COORDINATES_BD09: unknown = window.COORDINATES_BD09 || 5;
+
+ public getWebsite(): string {
+ return 'https://map.baidu.com';
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public asyncLoadAssets(language: string): Promise {
+ if (BaiduMapProvider.BMap) {
+ return Promise.resolve();
+ }
+
+ if (!window.onBMapCallback) {
+ window.onBMapCallback = () => {
+ BaiduMapProvider.BMap = window.BMap;
+ BaiduMapProvider.BMAP_NAVIGATION_CONTROL_ZOOM = window.BMAP_NAVIGATION_CONTROL_ZOOM || 3;
+ BaiduMapProvider.BMAP_ANCHOR_TOP_LEFT = window.BMAP_ANCHOR_TOP_LEFT || 0;
+ BaiduMapProvider.COORDINATES_WGS84 = window.COORDINATES_WGS84 || 1;
+ BaiduMapProvider.COORDINATES_BD09 = window.COORDINATES_BD09 || 5;
+ };
+ }
+
+ return asyncLoadAssets('js', services.generateBaiduMapJavascriptUrl('onBMapCallback'));
+ }
+
+ public createMapInstance(): MapInstance | null {
+ return new BaiduMapInstance();
+ }
+}
+
+export class BaiduMapInstance implements MapInstance {
+ public dependencyLoaded: boolean = false;
+ public inited: boolean = false;
+
+ public readonly defaultZoomLevel: number = 15;
+ public readonly minZoomLevel: number = 1;
+
+ private baiduMapInstance: unknown = null;
+ private baiduMapConverter: unknown = null;
+ private baiduMapNavigationControl: unknown = null;
+ private baiduMapCenterPosition: unknown = null;
+ private baiduMapCenterMarker: unknown | null;
+
+ constructor() {
+ this.dependencyLoaded = !!BaiduMapProvider.BMap;
+ }
+
+ public initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void {
+ if (!BaiduMapProvider.BMap) {
+ return;
+ }
+
+ const BMap = BaiduMapProvider.BMap;
+ const baiduMapInstance = new BMap.Map(mapContainer, {
+ maxZoom: 19
+ });
+ baiduMapInstance.enableScrollWheelZoom();
+
+ const baiduMapNavigationControl = new BMap.NavigationControl({
+ type: BaiduMapProvider.BMAP_NAVIGATION_CONTROL_ZOOM,
+ anchor: BaiduMapProvider.BMAP_ANCHOR_TOP_LEFT
+ });
+ baiduMapInstance.addControl(baiduMapNavigationControl);
+ baiduMapInstance.centerAndZoom(new BMap.Point(options.initCenter.longitude, options.initCenter.latitude), options.zoomLevel);
+
+ this.baiduMapInstance = baiduMapInstance;
+ this.baiduMapConverter = new BMap.Convertor();
+ this.baiduMapNavigationControl = baiduMapNavigationControl;
+ this.inited = true;
+ }
+
+ public setMapCenterTo(center: MapPosition, zoomLevel: number): void {
+ if (!BaiduMapProvider.BMap || !this.baiduMapInstance) {
+ return;
+ }
+
+ const BMap = BaiduMapProvider.BMap;
+
+ if (this.baiduMapCenterPosition
+ && this.baiduMapCenterPosition.originalLongitude === center.longitude
+ && this.baiduMapCenterPosition.originalLatitude === center.latitude
+ && this.baiduMapCenterPosition.convertedLongitude
+ && this.baiduMapCenterPosition.convertedLatitude
+ ) {
+ this.baiduMapInstance.centerAndZoom(new BMap.Point(this.baiduMapCenterPosition.convertedLongitude, this.baiduMapCenterPosition.convertedLatitude), zoomLevel);
+ return;
+ }
+
+ this.baiduMapCenterPosition = {
+ originalLongitude: center.longitude,
+ originalLatitude: center.latitude,
+ convertedLongitude: null,
+ convertedLatitude: null
+ };
+
+ const centerPoint = new BMap.Point(center.longitude, center.latitude);
+
+ if (this.baiduMapConverter) {
+ this.baiduMapConverter.translate([ centerPoint ], BaiduMapProvider.COORDINATES_WGS84, BaiduMapProvider.COORDINATES_BD09, data => {
+ let convertedCenterPoint = centerPoint;
+
+ if (data.status !== 0 || !data.points) {
+ logger.warn('baidu map geo position convert failed');
+ } else {
+ convertedCenterPoint = data.points[0];
+ this.baiduMapCenterPosition.convertedLongitude = convertedCenterPoint.lng;
+ this.baiduMapCenterPosition.convertedLatitude = convertedCenterPoint.lat;
+ }
+
+ this.baiduMapInstance.centerAndZoom(convertedCenterPoint, zoomLevel);
+ });
+ } else {
+ this.baiduMapInstance.centerAndZoom(centerPoint, zoomLevel);
+ }
+ }
+
+ public setMapCenterMarker(position: MapPosition): void {
+ if (!BaiduMapProvider.BMap || !this.baiduMapInstance) {
+ return;
+ }
+
+ const BMap = BaiduMapProvider.BMap;
+
+ if (this.baiduMapCenterPosition
+ && this.baiduMapCenterPosition.originalLongitude === position.longitude
+ && this.baiduMapCenterPosition.originalLatitude === position.latitude
+ && this.baiduMapCenterPosition.convertedLongitude
+ && this.baiduMapCenterPosition.convertedLatitude
+ ) {
+ this.setMaker(new BMap.Point(this.baiduMapCenterPosition.convertedLongitude, this.baiduMapCenterPosition.convertedLatitude));
+ return;
+ }
+
+ const markerPoint = new BMap.Point(position.longitude, position.latitude);
+
+ if (this.baiduMapConverter) {
+ this.baiduMapConverter.translate([ markerPoint ], BaiduMapProvider.COORDINATES_WGS84, BaiduMapProvider.COORDINATES_BD09, data => {
+ let convertedMarkPoint = markerPoint;
+
+ if (data.status !== 0 || !data.points) {
+ logger.warn('baidu map geo position convert failed');
+ } else {
+ convertedMarkPoint = data.points[0];
+ }
+
+ this.setMaker(convertedMarkPoint);
+ });
+ } else {
+ this.setMaker(markerPoint);
+ }
+ }
+
+ public removeMapCenterMarker(): void {
+ if (!this.baiduMapInstance || !this.baiduMapCenterMarker) {
+ return;
+ }
+
+ this.baiduMapInstance.removeOverlay(this.baiduMapCenterMarker);
+ this.baiduMapCenterMarker = null;
+ }
+
+ private setMaker(point: unknown): void {
+ if (!BaiduMapProvider.BMap || !this.baiduMapInstance) {
+ return;
+ }
+
+ const BMap = BaiduMapProvider.BMap;
+
+ if (!this.baiduMapCenterMarker) {
+ this.baiduMapCenterMarker = new BMap.Marker(point);
+ this.baiduMapInstance.addOverlay(this.baiduMapCenterMarker);
+ } else {
+ this.baiduMapCenterMarker.setPosition(point);
+ }
+ }
+}
diff --git a/src/lib/map/base.ts b/src/lib/map/base.ts
new file mode 100644
index 00000000..a5bc8ed8
--- /dev/null
+++ b/src/lib/map/base.ts
@@ -0,0 +1,31 @@
+export interface MapProvider {
+ getWebsite(): string;
+ asyncLoadAssets(language: string): Promise;
+ createMapInstance(): MapInstance | null;
+}
+
+export interface MapInstance {
+ dependencyLoaded: boolean;
+ inited: boolean;
+ readonly defaultZoomLevel: number;
+ readonly minZoomLevel: number;
+ initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void;
+ setMapCenterTo(center: MapPosition, zoomLevel: number): void;
+ setMapCenterMarker(position: MapPosition): void;
+ removeMapCenterMarker(): void;
+}
+
+export interface MapInstanceInitOptions {
+ readonly language?: string;
+ readonly initCenter: MapPosition;
+ readonly zoomLevel: number;
+ readonly text: {
+ readonly zoomIn: string;
+ readonly zoomOut: string;
+ }
+}
+
+export interface MapPosition {
+ latitude: number;
+ longitude: number;
+}
diff --git a/src/lib/map/googlemap.js b/src/lib/map/googlemap.js
deleted file mode 100644
index 3b5795ba..00000000
--- a/src/lib/map/googlemap.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import { asyncLoadAssets } from '@/lib/misc.ts';
-import services from '@/lib/services.js';
-
-const googleMapHolder = {
- googleMap: null,
- ControlPosition: {
- LEFT_TOP: (window.google && window.google.maps && window.google.maps.ControlPosition) ? window.google.maps.ControlPosition.LEFT_TOP : 5
- }
-};
-
-export function getGoogleMapWebsite() {
- return 'https://maps.google.com';
-}
-
-export function loadGoogleMapAssets(language) {
- if (googleMapHolder.googleMap) {
- return;
- }
-
- if (!window.onGoogleMapCallback) {
- window.onGoogleMapCallback = () => {
- if (window.google) {
- googleMapHolder.googleMap = window.google.maps;
- }
- };
- }
-
- return asyncLoadAssets('js', services.generateGoogleMapJavascriptUrl(language, 'onGoogleMapCallback'));
-}
-
-export function createGoogleMapHolder() {
- return {
- mapProvider: 'googlemap',
- dependencyLoaded: !!googleMapHolder.googleMap,
- inited: false,
- defaultZoomLevel: 14,
- minZoomLevel: 1,
- googleMapInstance: null,
- googleMapCenterMarker: null
- };
-}
-
-export function createGoogleMapInstance(mapHolder, mapContainer, options) {
- if (!googleMapHolder.googleMap) {
- return null;
- }
-
- const googleMap = googleMapHolder.googleMap;
-
- mapHolder.googleMapInstance = new googleMap.Map(mapContainer, {
- zoom: options.zoomLevel,
- center: {
- lat: options.initCenter.latitude,
- lng: options.initCenter.longitude
- },
- maxZoom: 19,
- zoomControl: true,
- mapTypeControl: false,
- scaleControl: false,
- streetViewControl: false,
- rotateControl: false,
- fullscreenControl: false,
- gestureHandling: 'greedy',
- zoomControlOptions: {
- position: googleMapHolder.ControlPosition.LEFT_TOP
- }
- });
- mapHolder.inited = true;
-}
-
-export function setGoogleMapCenterTo(mapHolder, center, zoomLevel) {
- if (!googleMapHolder.googleMap || !mapHolder.googleMapInstance) {
- return;
- }
-
- mapHolder.googleMapInstance.setCenter({
- lat: center.latitude,
- lng: center.longitude
- });
- mapHolder.googleMapInstance.setZoom(zoomLevel);
-}
-
-export function setGoogleMapCenterMaker(mapHolder, position) {
- if (!googleMapHolder.googleMap || !mapHolder.googleMapInstance) {
- return;
- }
-
- const googleMap = googleMapHolder.googleMap;
-
- if (!mapHolder.googleMapCenterMarker) {
- mapHolder.googleMapCenterMarker = new googleMap.Marker({
- position: {
- lat: position.latitude,
- lng: position.longitude
- },
- map: mapHolder.googleMapInstance
- });
- } else {
- mapHolder.googleMapCenterMarker.setPosition({
- lat: position.latitude,
- lng: position.longitude
- });
- }
-}
-
-export function removeGoogleMapCenterMaker(mapHolder) {
- if (!mapHolder.googleMapInstance || !mapHolder.googleMapCenterMarker) {
- return;
- }
-
- mapHolder.googleMapCenterMarker.setMap(null);
- mapHolder.googleMapCenterMarker = null;
-}
diff --git a/src/lib/map/googlemap.ts b/src/lib/map/googlemap.ts
new file mode 100644
index 00000000..a83549cf
--- /dev/null
+++ b/src/lib/map/googlemap.ts
@@ -0,0 +1,125 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
+
+import { asyncLoadAssets } from '@/lib/misc.ts';
+import services from '@/lib/services.js';
+
+export class GoogleMapProvider implements MapProvider {
+ public static GoogleMap: unknown = null;
+ public static ControlPosition = {
+ LEFT_TOP: (window.google && window.google.maps && window.google.maps.ControlPosition) ? window.google.maps.ControlPosition.LEFT_TOP : 5
+ };
+
+ public getWebsite(): string {
+ return 'https://maps.google.com';
+ }
+
+ public asyncLoadAssets(language: string): Promise {
+ if (GoogleMapProvider.GoogleMap) {
+ return Promise.resolve();
+ }
+
+ if (!window.onGoogleMapCallback) {
+ window.onGoogleMapCallback = () => {
+ if (window.google) {
+ GoogleMapProvider.GoogleMap = window.google.maps;
+ GoogleMapProvider.ControlPosition.LEFT_TOP = (window.google && window.google.maps && window.google.maps.ControlPosition) ? window.google.maps.ControlPosition.LEFT_TOP : 5;
+ }
+ };
+ }
+
+ return asyncLoadAssets('js', services.generateGoogleMapJavascriptUrl(language, 'onGoogleMapCallback'));
+ }
+
+ public createMapInstance(): MapInstance | null {
+ return new GoogleMapInstance();
+ }
+}
+
+export class GoogleMapInstance implements MapInstance {
+ public dependencyLoaded: boolean = false;
+ public inited: boolean = false;
+
+ public readonly defaultZoomLevel: number = 14;
+ public readonly minZoomLevel: number = 1;
+
+ private googleMapInstance: unknown = null;
+ private googleMapCenterMarker: unknown | null;
+
+ constructor() {
+ this.dependencyLoaded = !!GoogleMapProvider.GoogleMap;
+ }
+
+ public initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void {
+ if (!GoogleMapProvider.GoogleMap) {
+ return;
+ }
+
+ const googleMap = GoogleMapProvider.GoogleMap;
+
+ this.googleMapInstance = new googleMap.Map(mapContainer, {
+ zoom: options.zoomLevel,
+ center: {
+ lat: options.initCenter.latitude,
+ lng: options.initCenter.longitude
+ },
+ maxZoom: 19,
+ zoomControl: true,
+ mapTypeControl: false,
+ scaleControl: false,
+ streetViewControl: false,
+ rotateControl: false,
+ fullscreenControl: false,
+ gestureHandling: 'greedy',
+ zoomControlOptions: {
+ position: GoogleMapProvider.ControlPosition.LEFT_TOP
+ }
+ });
+ this.inited = true;
+ }
+
+ public setMapCenterTo(center: MapPosition, zoomLevel: number): void {
+ if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) {
+ return;
+ }
+
+ this.googleMapInstance.setCenter({
+ lat: center.latitude,
+ lng: center.longitude
+ });
+ this.googleMapInstance.setZoom(zoomLevel);
+ }
+
+ public setMapCenterMarker(position: MapPosition): void {
+ if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) {
+ return;
+ }
+
+ const googleMap = GoogleMapProvider.GoogleMap;
+
+ if (!this.googleMapCenterMarker) {
+ this.googleMapCenterMarker = new googleMap.Marker({
+ position: {
+ lat: position.latitude,
+ lng: position.longitude
+ },
+ map: this.googleMapInstance
+ });
+ } else {
+ this.googleMapCenterMarker.setPosition({
+ lat: position.latitude,
+ lng: position.longitude
+ });
+ }
+ }
+
+ public removeMapCenterMarker(): void {
+ if (!this.googleMapInstance || !this.googleMapCenterMarker) {
+ return;
+ }
+
+ this.googleMapCenterMarker.setMap(null);
+ this.googleMapCenterMarker = null;
+ }
+}
diff --git a/src/lib/map/index.js b/src/lib/map/index.js
deleted file mode 100644
index 3a3364d3..00000000
--- a/src/lib/map/index.js
+++ /dev/null
@@ -1,147 +0,0 @@
-import { LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
-import {
- getMapProvider
-} from '@/lib/server_settings.ts';
-
-import {
- loadLeafletMapAssets,
- createLeafletMapHolder,
- createLeafletMapInstance,
- setLeafletMapCenterTo,
- setLeafletMapCenterMaker,
- removeLeafletMapCenterMaker
-} from './leaflet.js';
-
-import {
- getGoogleMapWebsite,
- loadGoogleMapAssets,
- createGoogleMapHolder,
- createGoogleMapInstance,
- setGoogleMapCenterTo,
- setGoogleMapCenterMaker,
- removeGoogleMapCenterMaker
-} from './googlemap.js';
-
-import {
- getBaiduMapWebsite,
- loadBaiduMapAssets,
- createBaiduMapHolder,
- createBaiduMapInstance,
- setBaiduMapCenterTo,
- setBaiduMapCenterMaker,
- removeBaiduMapCenterMaker
-} from './baidumap.js';
-
-import {
- getAmapWebsite,
- loadAmapAssets,
- createAmapHolder,
- createAmapInstance,
- setAmapCenterTo,
- setAmapCenterMaker,
- removeAmapCenterMaker
-} from './amap.js';
-
-export function getMapWebsite() {
- if (getMapProvider() === 'custom') {
- return '';
- } else if (LEAFLET_TILE_SOURCES[getMapProvider()]) {
- return LEAFLET_TILE_SOURCES[getMapProvider()].website;
- } else if (getMapProvider() === 'googlemap') {
- return getGoogleMapWebsite();
- } else if (getMapProvider() === 'baidumap') {
- return getBaiduMapWebsite();
- } else if (getMapProvider() === 'amap') {
- return getAmapWebsite();
- }
-}
-
-export function loadMapAssets(language) {
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- return loadLeafletMapAssets(language);
- } else if (getMapProvider() === 'googlemap') {
- return loadGoogleMapAssets(language);
- } else if (getMapProvider() === 'baidumap') {
- return loadBaiduMapAssets(language);
- } else if (getMapProvider() === 'amap') {
- return loadAmapAssets(language);
- }
-}
-
-export function createMapHolder() {
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- return createLeafletMapHolder(getMapProvider());
- } else if (getMapProvider() === 'googlemap') {
- return createGoogleMapHolder(getMapProvider());
- } else if (getMapProvider() === 'baidumap') {
- return createBaiduMapHolder(getMapProvider());
- } else if (getMapProvider() === 'amap') {
- return createAmapHolder(getMapProvider());
- } else {
- return null;
- }
-}
-
-export function initMapInstance(mapHolder, mapContainer, options) {
- if (!mapHolder) {
- return;
- }
-
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- createLeafletMapInstance(mapHolder, mapContainer, options);
- } else if (mapHolder.mapProvider === 'googlemap') {
- createGoogleMapInstance(mapHolder, mapContainer, options);
- } else if (mapHolder.mapProvider === 'baidumap') {
- createBaiduMapInstance(mapHolder, mapContainer, options);
- } else if (mapHolder.mapProvider === 'amap') {
- createAmapInstance(mapHolder, mapContainer, options);
- }
-}
-
-export function setMapCenterTo(mapHolder, center, zoomLevel) {
- if (!mapHolder) {
- return;
- }
-
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- setLeafletMapCenterTo(mapHolder, center, zoomLevel);
- } else if (mapHolder.mapProvider === 'googlemap') {
- setGoogleMapCenterTo(mapHolder, center, zoomLevel);
- } else if (mapHolder.mapProvider === 'baidumap') {
- setBaiduMapCenterTo(mapHolder, center, zoomLevel);
- } else if (mapHolder.mapProvider === 'amap') {
- setAmapCenterTo(mapHolder, center, zoomLevel);
- }
-}
-
-export function setMapCenterMarker(mapHolder, position) {
- if (!mapHolder) {
- return;
- }
-
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- setLeafletMapCenterMaker(mapHolder, position);
- } else if (mapHolder.mapProvider === 'googlemap') {
- setGoogleMapCenterMaker(mapHolder, position);
- } else if (mapHolder.mapProvider === 'baidumap') {
- setBaiduMapCenterMaker(mapHolder, position);
- } else if (mapHolder.mapProvider === 'amap') {
- setAmapCenterMaker(mapHolder, position);
- }
-}
-
-export function removeMapCenterMarker(mapHolder) {
- if (!mapHolder) {
- return;
- }
-
- if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
- removeLeafletMapCenterMaker(mapHolder);
- } else if (mapHolder.mapProvider === 'googlemap') {
- removeGoogleMapCenterMaker(mapHolder);
- } else if (mapHolder.mapProvider === 'baidumap') {
- removeBaiduMapCenterMaker(mapHolder);
- } else if (mapHolder.mapProvider === 'amap') {
- removeAmapCenterMaker(mapHolder);
- }
-}
diff --git a/src/lib/map/index.ts b/src/lib/map/index.ts
new file mode 100644
index 00000000..62d1fa00
--- /dev/null
+++ b/src/lib/map/index.ts
@@ -0,0 +1,36 @@
+import { LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
+import { getMapProvider } from '@/lib/server_settings.ts';
+
+import type { MapProvider, MapInstance } from './base.ts';
+import { LeafletMapProvider } from './leaflet.ts';
+import { GoogleMapProvider } from './googlemap.ts';
+import { BaiduMapProvider } from './baidumap.ts';
+import { AmapMapProvider } from './amap.ts';
+
+let mapProvider: MapProvider | null = null;
+
+export function initMapProvider(language: string): void {
+ const mapProviderType = getMapProvider();
+
+ if (LEAFLET_TILE_SOURCES[mapProviderType] || mapProviderType === 'custom') {
+ mapProvider = new LeafletMapProvider(mapProviderType);
+ } else if (mapProviderType === 'googlemap') {
+ mapProvider = new GoogleMapProvider();
+ } else if (mapProviderType === 'baidumap') {
+ mapProvider = new BaiduMapProvider();
+ } else if (mapProviderType === 'amap') {
+ mapProvider = new AmapMapProvider();
+ }
+
+ if (mapProvider) {
+ mapProvider.asyncLoadAssets(language);
+ }
+}
+
+export function getMapWebsite(): string {
+ return mapProvider?.getWebsite() || '';
+}
+
+export function createMapInstance(): MapInstance | null {
+ return mapProvider?.createMapInstance() || null;
+}
diff --git a/src/lib/map/leaflet.js b/src/lib/map/leaflet.js
deleted file mode 100644
index fc693b27..00000000
--- a/src/lib/map/leaflet.js
+++ /dev/null
@@ -1,199 +0,0 @@
-import { LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
-import {
- isMapDataFetchProxyEnabled,
- getCustomMapTileLayerUrl,
- getCustomMapAnnotationLayerUrl,
- isCustomMapAnnotationLayerDataFetchProxyEnabled,
- getCustomMapMinZoomLevel,
- getCustomMapMaxZoomLevel,
- getCustomMapDefaultZoomLevel,
- getTomTomMapAPIKey,
- getTianDiTuMapAPIKey
-} from '@/lib/server_settings.ts';
-import services from '@/lib/services.js';
-
-const leafletHolder = {
- leaflet: null
-};
-
-export function loadLeafletMapAssets() {
- return Promise.all([
- import('leaflet/dist/leaflet.css'),
- import('leaflet/dist/leaflet-src.esm.js').then(leaflet => leafletHolder.leaflet = leaflet)
- ]);
-}
-
-export function createLeafletMapHolder(mapProvider) {
- const mapTileSource = LEAFLET_TILE_SOURCES[mapProvider];
-
- if (mapProvider !== 'custom' && !mapTileSource) {
- return null;
- }
-
- return {
- mapProvider: mapProvider,
- dependencyLoaded: !!leafletHolder.leaflet,
- inited: false,
- defaultZoomLevel: mapProvider !== 'custom' ? mapTileSource.defaultZoomLevel : getCustomMapDefaultZoomLevel(),
- minZoomLevel: mapProvider !== 'custom' ? mapTileSource.minZoom : getCustomMapMinZoomLevel(),
- leafletInstance: null,
- leafletTileLayer: null,
- leafletAnnotationLayer: null,
- leafletZoomControl: null,
- leafletAttribution: null,
- leafletCenterMarker: null
- };
-}
-
-export function createLeafletMapInstance(mapHolder, mapContainer, options) {
- if (!leafletHolder.leaflet) {
- return null;
- }
-
- const leaflet = leafletHolder.leaflet;
- const leafletInstance = leaflet.map(mapContainer, {
- center: [ options.initCenter.latitude, options.initCenter.longitude ],
- zoom: options.zoomLevel,
- attributionControl: false,
- zoomControl: false
- });
- let mapTileSource = null;
-
- if (mapHolder.mapProvider !== 'custom') {
- mapTileSource = Object.assign({}, LEAFLET_TILE_SOURCES[mapHolder.mapProvider]);
- } else {
- mapTileSource = createCustomMapSource();
- }
-
- if (isMapDataFetchProxyEnabled()) {
- mapTileSource.tileUrlFormat = services.generateMapProxyTileImageUrl(mapHolder.mapProvider, options.language);
- mapTileSource.tileUrlSubDomains = '';
- } else if (mapTileSource.tileUrlExtraParams) {
- mapTileSource.tileUrlFormat = getFinalUrlFormat(mapTileSource.tileUrlFormat, mapTileSource.tileUrlExtraParams, options);
- }
-
- const tileLayer = leaflet.tileLayer(mapTileSource.tileUrlFormat, {
- subdomains: mapTileSource.tileUrlSubDomains,
- maxZoom: mapTileSource.maxZoom,
- minZoom: mapTileSource.minZoom
- });
- tileLayer.addTo(leafletInstance);
-
- if (mapTileSource.annotationUrlFormat || (mapHolder.mapProvider === 'custom' && isCustomMapAnnotationLayerDataFetchProxyEnabled())) {
- if (isMapDataFetchProxyEnabled()) {
- mapTileSource.annotationUrlFormat = services.generateMapProxyAnnotationImageUrl(mapHolder.mapProvider, options.language);
- mapTileSource.annotationUrlSubDomains = '';
- } else if (mapTileSource.annotationUrlExtraParams) {
- mapTileSource.annotationUrlFormat = getFinalUrlFormat(mapTileSource.annotationUrlFormat, mapTileSource.annotationUrlExtraParams, options);
- }
-
- const annotationLayer = leaflet.tileLayer(mapTileSource.annotationUrlFormat, {
- subdomains: mapTileSource.annotationUrlSubDomains,
- maxZoom: mapTileSource.maxZoom,
- minZoom: mapTileSource.minZoom
- });
- annotationLayer.addTo(leafletInstance);
-
- mapHolder.leafletAnnotationLayer = annotationLayer;
- }
-
- const zoomControl = leaflet.control.zoom({
- zoomInTitle: options.text.zoomIn,
- zoomOutTitle: options.text.zoomOut
- });
- zoomControl.addTo(leafletInstance);
-
- if (mapTileSource.attribution) {
- const attribution = leaflet.control.attribution({
- prefix: false
- });
- attribution.addAttribution(mapTileSource.attribution);
- attribution.addTo(leafletInstance);
- mapHolder.leafletAttribution = attribution;
- }
-
- mapHolder.leafletInstance = leafletInstance;
- mapHolder.leafletTileLayer = tileLayer;
- mapHolder.leafletZoomControl = zoomControl;
- mapHolder.inited = true;
-}
-
-export function setLeafletMapCenterTo(mapHolder, center, zoomLevel) {
- if (!mapHolder.leafletInstance) {
- return;
- }
-
- mapHolder.leafletInstance.setView([ center.latitude, center.longitude ], zoomLevel);
-}
-
-export function setLeafletMapCenterMaker(mapHolder, position) {
- if (!leafletHolder.leaflet || !mapHolder.leafletInstance) {
- return;
- }
-
- const leaflet = leafletHolder.leaflet;
-
- if (!mapHolder.leafletCenterMarker) {
- const markerIcon = leaflet.icon({
- iconUrl: 'img/map-marker-icon.png',
- iconRetinaUrl: 'img/map-marker-icon-2x.png',
- iconSize: [25, 32],
- iconAnchor: [12, 32],
- shadowUrl: 'img/map-marker-shadow.png',
- shadowSize: [41, 32]
- });
- mapHolder.leafletCenterMarker = leaflet.marker([ position.latitude, position.longitude ], {
- icon: markerIcon
- });
- mapHolder.leafletCenterMarker.addTo(mapHolder.leafletInstance);
- } else {
- mapHolder.leafletCenterMarker.setLatLng([ position.latitude, position.longitude ]);
- }
-}
-
-export function removeLeafletMapCenterMaker(mapHolder) {
- if (!mapHolder.leafletInstance || !mapHolder.leafletCenterMarker) {
- return;
- }
-
- mapHolder.leafletCenterMarker.remove();
- mapHolder.leafletCenterMarker = null;
-}
-
-function createCustomMapSource() {
- return {
- tileUrlFormat: getCustomMapTileLayerUrl(),
- tileUrlSubDomains: '',
- annotationUrlFormat: getCustomMapAnnotationLayerUrl(),
- annotationUrlSubDomains: '',
- minZoom: getCustomMapMinZoomLevel(),
- maxZoom: getCustomMapMaxZoomLevel(),
- defaultZoomLevel: getCustomMapDefaultZoomLevel()
- };
-}
-
-function getFinalUrlFormat(urlFormat, urlExtraParams, options) {
- const params = [];
-
- for (let i = 0; i < urlExtraParams.length; i++) {
- const param = urlExtraParams[i];
-
- if (param.paramValueType === 'tomtom_key') {
- params.push(param.paramName + '=' + getTomTomMapAPIKey());
- } else if (param.paramValueType === 'tianditu_key') {
- params.push(param.paramName + '=' + getTianDiTuMapAPIKey());
- } else if (param.paramValueType === 'language' && options.language) {
- params.push(param.paramName + '=' + options.language);
- }
- }
-
- if (params.length) {
- if (urlFormat.indexOf('?') >= 0) {
- urlFormat = urlFormat + '&' + params.join('&');
- } else {
- urlFormat = urlFormat + '?' + params.join('&');
- }
- }
-
- return urlFormat;
-}
diff --git a/src/lib/map/leaflet.ts b/src/lib/map/leaflet.ts
new file mode 100644
index 00000000..e41fdb07
--- /dev/null
+++ b/src/lib/map/leaflet.ts
@@ -0,0 +1,234 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import { type LeafletTileSource, type LeafletTileSourceExtraParam, LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
+
+import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
+
+import {
+ isMapDataFetchProxyEnabled,
+ getCustomMapTileLayerUrl,
+ getCustomMapAnnotationLayerUrl,
+ isCustomMapAnnotationLayerDataFetchProxyEnabled,
+ getCustomMapMinZoomLevel,
+ getCustomMapMaxZoomLevel,
+ getCustomMapDefaultZoomLevel,
+ getTomTomMapAPIKey,
+ getTianDiTuMapAPIKey
+} from '@/lib/server_settings.ts';
+import services from '@/lib/services.js';
+
+export class LeafletMapProvider implements MapProvider {
+ public static Leaflet: unknown = null;
+ private readonly mapProvider: string;
+
+ public constructor(mapProvider: string) {
+ this.mapProvider = mapProvider;
+ }
+
+ public getWebsite(): string {
+ if (this.mapProvider === 'custom') {
+ return '';
+ } else if (LEAFLET_TILE_SOURCES[this.mapProvider]) {
+ return LEAFLET_TILE_SOURCES[this.mapProvider].website || '';
+ } else {
+ return '';
+ }
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public asyncLoadAssets(language: string): Promise {
+ return Promise.all([
+ import('leaflet/dist/leaflet.css'),
+ import('leaflet/dist/leaflet-src.esm.js').then(leaflet => LeafletMapProvider.Leaflet = leaflet)
+ ]);
+ }
+
+ public createMapInstance(): MapInstance | null {
+ const mapTileSource = LEAFLET_TILE_SOURCES[this.mapProvider];
+
+ if (this.mapProvider !== 'custom' && !mapTileSource) {
+ return null;
+ }
+
+ return new LeafletMapInstance(this.mapProvider, mapTileSource);
+ }
+}
+
+export class LeafletMapInstance implements MapInstance {
+ public dependencyLoaded: boolean = false;
+ public inited: boolean = false;
+
+ public readonly defaultZoomLevel: number;
+ public readonly minZoomLevel: number;
+
+ private readonly mapProvider: string;
+ private readonly presetMapTileSource: LeafletTileSource;
+
+ private leafletInstance: unknown | null;
+ private leafletTileLayer: unknown | null;
+ private leafletAnnotationLayer: unknown | null;
+ private leafletZoomControl: unknown | null;
+ private leafletAttribution: unknown | null;
+ private leafletCenterMarker: unknown | null;
+
+ constructor(mapProvider: string, mapTileSource: LeafletTileSource) {
+ this.dependencyLoaded = !!LeafletMapProvider.Leaflet;
+
+ this.mapProvider = mapProvider;
+ this.presetMapTileSource = mapTileSource;
+
+ this.defaultZoomLevel = this.presetMapTileSource?.defaultZoomLevel || getCustomMapDefaultZoomLevel();
+ this.minZoomLevel = this.presetMapTileSource?.minZoom || getCustomMapMinZoomLevel();
+ }
+
+ public initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void {
+ if (!LeafletMapProvider.Leaflet) {
+ return;
+ }
+
+ const leaflet = LeafletMapProvider.Leaflet;
+ const leafletInstance = leaflet.map(mapContainer, {
+ center: [ options.initCenter.latitude, options.initCenter.longitude ],
+ zoom: options.zoomLevel,
+ attributionControl: false,
+ zoomControl: false
+ });
+
+ let tileUrlFormat, tileUrlSubDomains, annotationUrlFormat, annotationUrlSubDomains: string | undefined;
+ let minZoom, maxZoom: number;
+
+ if (this.mapProvider !== 'custom') {
+ tileUrlFormat = this.presetMapTileSource?.tileUrlFormat;
+ tileUrlSubDomains = this.presetMapTileSource?.tileUrlSubDomains;
+ annotationUrlFormat = this.presetMapTileSource?.annotationUrlFormat;
+ annotationUrlSubDomains = this.presetMapTileSource?.annotationUrlSubDomains;
+ minZoom = this.presetMapTileSource?.minZoom;
+ maxZoom = this.presetMapTileSource?.maxZoom;
+ } else {
+ tileUrlFormat = getCustomMapTileLayerUrl();
+ annotationUrlFormat = getCustomMapAnnotationLayerUrl();
+ minZoom = getCustomMapMinZoomLevel();
+ maxZoom = getCustomMapMaxZoomLevel();
+ }
+
+ if (isMapDataFetchProxyEnabled()) {
+ tileUrlFormat = services.generateMapProxyTileImageUrl(this.mapProvider, options.language);
+ tileUrlSubDomains = '';
+ } else if (this.presetMapTileSource && this.presetMapTileSource.tileUrlExtraParams) {
+ tileUrlFormat = this.getFinalUrlFormat(this.presetMapTileSource.tileUrlFormat as string, this.presetMapTileSource.tileUrlExtraParams, options);
+ }
+
+ const tileLayer = leaflet.tileLayer(tileUrlFormat, {
+ subdomains: tileUrlSubDomains,
+ maxZoom: maxZoom,
+ minZoom: minZoom
+ });
+ tileLayer.addTo(leafletInstance);
+
+ if (annotationUrlFormat || (this.mapProvider === 'custom' && isCustomMapAnnotationLayerDataFetchProxyEnabled())) {
+ if (isMapDataFetchProxyEnabled()) {
+ annotationUrlFormat = services.generateMapProxyAnnotationImageUrl(this.mapProvider, options.language);
+ annotationUrlSubDomains = '';
+ } else if (this.presetMapTileSource && this.presetMapTileSource.annotationUrlExtraParams) {
+ annotationUrlFormat = this.getFinalUrlFormat(this.presetMapTileSource.annotationUrlFormat as string, this.presetMapTileSource.annotationUrlExtraParams, options);
+ }
+
+ const annotationLayer = leaflet.tileLayer(annotationUrlFormat, {
+ subdomains: annotationUrlSubDomains,
+ maxZoom: maxZoom,
+ minZoom: minZoom
+ });
+ annotationLayer.addTo(leafletInstance);
+
+ this.leafletAnnotationLayer = annotationLayer;
+ }
+
+ const zoomControl = leaflet.control.zoom({
+ zoomInTitle: options.text.zoomIn,
+ zoomOutTitle: options.text.zoomOut
+ });
+ zoomControl.addTo(leafletInstance);
+
+ if (this.presetMapTileSource && this.presetMapTileSource.attribution) {
+ const attribution = leaflet.control.attribution({
+ prefix: false
+ });
+ attribution.addAttribution(this.presetMapTileSource.attribution);
+ attribution.addTo(leafletInstance);
+ this.leafletAttribution = attribution;
+ }
+
+ this.leafletInstance = leafletInstance;
+ this.leafletTileLayer = tileLayer;
+ this.leafletZoomControl = zoomControl;
+ this.inited = true;
+ }
+
+ public setMapCenterTo(center: MapPosition, zoomLevel: number): void {
+ if (!this.leafletInstance) {
+ return;
+ }
+
+ this.leafletInstance.setView([ center.latitude, center.longitude ], zoomLevel);
+ }
+
+ public setMapCenterMarker(position: MapPosition): void {
+ if (!LeafletMapProvider.Leaflet || !this.leafletInstance) {
+ return;
+ }
+
+ const leaflet = LeafletMapProvider.Leaflet;
+
+ if (!this.leafletCenterMarker) {
+ const markerIcon = leaflet.icon({
+ iconUrl: 'img/map-marker-icon.png',
+ iconRetinaUrl: 'img/map-marker-icon-2x.png',
+ iconSize: [25, 32],
+ iconAnchor: [12, 32],
+ shadowUrl: 'img/map-marker-shadow.png',
+ shadowSize: [41, 32]
+ });
+ this.leafletCenterMarker = leaflet.marker([ position.latitude, position.longitude ], {
+ icon: markerIcon
+ });
+ this.leafletCenterMarker.addTo(this.leafletInstance);
+ } else {
+ this.leafletCenterMarker.setLatLng([ position.latitude, position.longitude ]);
+ }
+ }
+
+ public removeMapCenterMarker(): void {
+ if (!this.leafletInstance || !this.leafletCenterMarker) {
+ return;
+ }
+
+ this.leafletCenterMarker.remove();
+ this.leafletCenterMarker = null;
+ }
+
+ private getFinalUrlFormat(urlFormat: string, urlExtraParams: LeafletTileSourceExtraParam[], options: MapInstanceInitOptions) {
+ const params: string[] = [];
+
+ for (let i = 0; i < urlExtraParams.length; i++) {
+ const param = urlExtraParams[i];
+
+ if (param.paramValueType === 'tomtom_key') {
+ params.push(param.paramName + '=' + getTomTomMapAPIKey());
+ } else if (param.paramValueType === 'tianditu_key') {
+ params.push(param.paramName + '=' + getTianDiTuMapAPIKey());
+ } else if (param.paramValueType === 'language' && options.language) {
+ params.push(param.paramName + '=' + options.language);
+ }
+ }
+
+ if (params.length) {
+ if (urlFormat.indexOf('?') >= 0) {
+ urlFormat = urlFormat + '&' + params.join('&');
+ } else {
+ urlFormat = urlFormat + '?' + params.join('&');
+ }
+ }
+
+ return urlFormat;
+ }
+}
diff --git a/src/views/desktop/AboutPage.vue b/src/views/desktop/AboutPage.vue
index 08cd7269..568a2e71 100644
--- a/src/views/desktop/AboutPage.vue
+++ b/src/views/desktop/AboutPage.vue
@@ -125,7 +125,7 @@ import { useUserStore } from '@/stores/user.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import { getMapProvider } from '@/lib/server_settings.ts';
-import { getMapWebsite } from '@/lib/map/index.js';
+import { getMapWebsite } from '@/lib/map/index.ts';
import { getLicense, getThirdPartyLicenses } from '@/lib/licenses.ts';
export default {
diff --git a/src/views/mobile/AboutPage.vue b/src/views/mobile/AboutPage.vue
index 38d32ff2..c718acd3 100644
--- a/src/views/mobile/AboutPage.vue
+++ b/src/views/mobile/AboutPage.vue
@@ -63,7 +63,7 @@ import { useUserStore } from '@/stores/user.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import { getMapProvider } from '@/lib/server_settings.ts';
-import { getMapWebsite } from '@/lib/map/index.js';
+import { getMapWebsite } from '@/lib/map/index.ts';
import { getLicense, getThirdPartyLicenses } from '@/lib/licenses.ts';
export default {