migrate map code to typescript
This commit is contained in:
+2
-2
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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: {
|
||||
|
||||
@@ -8,112 +8,110 @@
|
||||
v-if="!mapSupported || !mapDependencyLoaded"></slot>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
copyObjectTo
|
||||
} from '@/lib/common.ts';
|
||||
import {
|
||||
createMapHolder,
|
||||
initMapInstance,
|
||||
setMapCenterTo,
|
||||
setMapCenterMarker,
|
||||
removeMapCenterMarker
|
||||
} from '@/lib/map/index.js';
|
||||
<script setup lang="ts">
|
||||
import { type Ref, ref, computed, useTemplateRef } from 'vue';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'height',
|
||||
'mapClass',
|
||||
'mapStyle',
|
||||
'geoLocation'
|
||||
],
|
||||
expose: [
|
||||
'init'
|
||||
],
|
||||
data() {
|
||||
this.mapHolder = createMapHolder();
|
||||
import { useI18n } from '@/lib/i18n.js';
|
||||
|
||||
return {
|
||||
mapSupported: !!this.mapHolder,
|
||||
mapDependencyLoaded: this.mapHolder && this.mapHolder.dependencyLoaded,
|
||||
mapInited: false,
|
||||
initCenter: {
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
},
|
||||
zoomLevel: 1
|
||||
import { copyObjectTo } from '@/lib/common.ts';
|
||||
import type { MapInstance, MapPosition } from '@/lib/map/base.ts';
|
||||
import { createMapInstance } from '@/lib/map/index.ts';
|
||||
|
||||
const props = defineProps<{
|
||||
height?: string;
|
||||
mapClass?: string;
|
||||
mapStyle?: Record<string, string>;
|
||||
geoLocation?: MapPosition;
|
||||
}>();
|
||||
|
||||
const { tt, getCurrentLanguageInfo } = useI18n();
|
||||
|
||||
const mapContainer: Ref<HTMLElement> = useTemplateRef('mapContainer');
|
||||
const mapInstance: Ref<MapInstance> = ref(createMapInstance());
|
||||
const initCenter: Ref<MapPosition> = ref({
|
||||
latitude: 0,
|
||||
longitude: 0
|
||||
});
|
||||
const zoomLevel: Ref<number> = ref(1);
|
||||
|
||||
const mapSupported = computed<boolean>(() => {
|
||||
return !!mapInstance.value;
|
||||
});
|
||||
|
||||
const mapDependencyLoaded = computed<boolean>(() => {
|
||||
return mapInstance.value && mapInstance.value.dependencyLoaded;
|
||||
});
|
||||
|
||||
const finalMapStyle = computed<Record<string, string>>(() => {
|
||||
const styles = copyObjectTo(props.mapStyle, {});
|
||||
|
||||
if (props.height) {
|
||||
styles.height = props.height;
|
||||
}
|
||||
|
||||
if (!mapSupported.value || !mapDependencyLoaded.value) {
|
||||
styles.height = '0';
|
||||
}
|
||||
|
||||
return styles;
|
||||
});
|
||||
|
||||
function init() {
|
||||
let isFirstInit = false;
|
||||
let centerChanged = false;
|
||||
|
||||
if (!mapSupported.value || !mapDependencyLoaded.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.geoLocation && (props.geoLocation.longitude || props.geoLocation.latitude)) {
|
||||
if (initCenter.value.latitude !== props.geoLocation.latitude || initCenter.value.longitude !== props.geoLocation.longitude) {
|
||||
initCenter.value.latitude = props.geoLocation.latitude;
|
||||
initCenter.value.longitude = props.geoLocation.longitude;
|
||||
zoomLevel.value = mapInstance.value.defaultZoomLevel;
|
||||
|
||||
centerChanged = true;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
finalMapStyle() {
|
||||
const styles = copyObjectTo(this.mapStyle, {});
|
||||
} else if (!props.geoLocation || (!props.geoLocation.longitude && !props.geoLocation.latitude)) {
|
||||
if (initCenter.value.latitude || initCenter.value.longitude) {
|
||||
initCenter.value.latitude = 0;
|
||||
initCenter.value.longitude = 0;
|
||||
zoomLevel.value = mapInstance.value.minZoomLevel;
|
||||
|
||||
if (this.height) {
|
||||
styles.height = this.height;
|
||||
}
|
||||
|
||||
if (!this.mapSupported || !this.mapDependencyLoaded) {
|
||||
styles.height = '0';
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
let isFirstInit = false;
|
||||
let centerChanged = false;
|
||||
|
||||
if (!this.mapSupported || !this.mapDependencyLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.geoLocation && (this.geoLocation.longitude || this.geoLocation.latitude)) {
|
||||
if (this.initCenter.latitude !== this.geoLocation.latitude || this.initCenter.longitude !== this.geoLocation.longitude) {
|
||||
this.initCenter.latitude = this.geoLocation.latitude;
|
||||
this.initCenter.longitude = this.geoLocation.longitude;
|
||||
this.zoomLevel = this.mapHolder.defaultZoomLevel;
|
||||
|
||||
centerChanged = true;
|
||||
}
|
||||
} else if (!this.geoLocation || (!this.geoLocation.longitude && !this.geoLocation.latitude)) {
|
||||
if (this.initCenter.latitude || this.initCenter.longitude) {
|
||||
this.initCenter.latitude = 0;
|
||||
this.initCenter.longitude = 0;
|
||||
this.zoomLevel = this.mapHolder.minZoomLevel;
|
||||
|
||||
centerChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.mapHolder.inited) {
|
||||
const languageInfo = this.$locale.getCurrentLanguageInfo();
|
||||
|
||||
initMapInstance(this.mapHolder, this.$refs.mapContainer, {
|
||||
language: languageInfo ? languageInfo.alternativeLanguageTag : null,
|
||||
initCenter: this.initCenter,
|
||||
zoomLevel: this.zoomLevel,
|
||||
text: {
|
||||
zoomIn: this.$t('Zoom in'),
|
||||
zoomOut: this.$t('Zoom out'),
|
||||
}
|
||||
});
|
||||
|
||||
if (this.mapHolder.inited) {
|
||||
isFirstInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFirstInit || centerChanged) {
|
||||
setMapCenterTo(this.mapHolder, this.initCenter, this.zoomLevel);
|
||||
}
|
||||
|
||||
if (centerChanged && this.zoomLevel > this.mapHolder.minZoomLevel) {
|
||||
setMapCenterMarker(this.mapHolder, this.initCenter);
|
||||
} else if (centerChanged && this.zoomLevel <= this.mapHolder.minZoomLevel) {
|
||||
removeMapCenterMarker(this.mapHolder);
|
||||
}
|
||||
centerChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mapInstance.value.inited) {
|
||||
const languageInfo = getCurrentLanguageInfo();
|
||||
|
||||
mapInstance.value.initMapInstance(mapContainer.value, {
|
||||
language: languageInfo?.alternativeLanguageTag,
|
||||
initCenter: initCenter.value,
|
||||
zoomLevel: zoomLevel.value,
|
||||
text: {
|
||||
zoomIn: tt('Zoom in'),
|
||||
zoomOut: tt('Zoom out'),
|
||||
}
|
||||
});
|
||||
|
||||
if (mapInstance.value.inited) {
|
||||
isFirstInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFirstInit || centerChanged) {
|
||||
mapInstance.value.setMapCenterTo(initCenter.value, zoomLevel.value);
|
||||
}
|
||||
|
||||
if (centerChanged && zoomLevel.value > mapInstance.value.minZoomLevel) {
|
||||
mapInstance.value.setMapCenterMarker(initCenter.value);
|
||||
} else if (centerChanged && zoomLevel.value <= mapInstance.value.minZoomLevel) {
|
||||
mapInstance.value.removeMapCenterMarker();
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init
|
||||
});
|
||||
</script>
|
||||
|
||||
+7
-7
@@ -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<string, PresetLeafletTileSource> = {
|
||||
export const LEAFLET_TILE_SOURCES: Record<string, LeafletTileSource> = {
|
||||
'openstreetmap': {
|
||||
tileUrlFormat: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
tileUrlSubDomains: 'abc',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<unknown> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<unknown> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
export interface MapProvider {
|
||||
getWebsite(): string;
|
||||
asyncLoadAssets(language: string): Promise<unknown>;
|
||||
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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<unknown> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<unknown> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user