mirror of https://gitee.com/antv-l7/antv-l7
Feat custom map (#1326)
* chore(map): 地图模块重构 * feat: lealetMap for l7 * chore: amap baseservice 重构 * fix: 修改amap 样式 * fix: 单词拼写
This commit is contained in:
parent
b43a44844f
commit
fac48aede1
|
@ -1,5 +1,5 @@
|
||||||
import { PolygonLayer, Scene } from '@antv/l7';
|
import { PolygonLayer, Scene } from '@antv/l7';
|
||||||
import { Mapbox } from '@antv/l7-maps';
|
import { Map } from '@antv/l7-maps';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useData, addLayers } from './useLine';
|
import { useData, addLayers } from './useLine';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export default () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
map: new Mapbox({
|
map: new Map({
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
style: 'light',
|
style: 'light',
|
||||||
center: [-96, 37.8],
|
center: [-96, 37.8],
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
"@types/gl": "^4.1.0",
|
"@types/gl": "^4.1.0",
|
||||||
"@types/hoist-non-react-statics": "^3.3.1",
|
"@types/hoist-non-react-statics": "^3.3.1",
|
||||||
"@types/jest": "^25.2.1",
|
"@types/jest": "^25.2.1",
|
||||||
|
"@types/leaflet": "^1.7.11",
|
||||||
"@types/node": "13.11.1",
|
"@types/node": "13.11.1",
|
||||||
"@types/offscreencanvas": "^2019.7.0",
|
"@types/offscreencanvas": "^2019.7.0",
|
||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
|
@ -101,6 +102,7 @@
|
||||||
"jest": "^24.9.0",
|
"jest": "^24.9.0",
|
||||||
"jest-canvas-mock": "^2.4.0",
|
"jest-canvas-mock": "^2.4.0",
|
||||||
"jest-styled-components": "^6.2.1",
|
"jest-styled-components": "^6.2.1",
|
||||||
|
"leaflet": "^1.8.0",
|
||||||
"lerc": "^3.0.0",
|
"lerc": "^3.0.0",
|
||||||
"lerna": "^3.16.4",
|
"lerna": "^3.16.4",
|
||||||
"lint-staged": "^9.2.4",
|
"lint-staged": "^9.2.4",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/async-hook": "^2.1.0",
|
"@antv/async-hook": "^2.2.2",
|
||||||
"@antv/l7-utils": "2.9.26",
|
"@antv/l7-utils": "2.9.26",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"@turf/helpers": "^6.1.4",
|
"@turf/helpers": "^6.1.4",
|
||||||
|
|
|
@ -18,11 +18,7 @@ export interface ISceneConfig extends IRenderConfig {
|
||||||
stencil?: boolean;
|
stencil?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// interface IValidateResult {
|
|
||||||
// valid: boolean;
|
|
||||||
// errors: Ajv.ErrorObject[] | null | undefined;
|
|
||||||
// errorText: string | null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export interface IGlobalConfigService {
|
export interface IGlobalConfigService {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,12 +49,12 @@ export interface IMapService<RawMap = {}> {
|
||||||
setBgColor(color: string): void;
|
setBgColor(color: string): void;
|
||||||
init(): void;
|
init(): void;
|
||||||
initMiniMap?(): void;
|
initMiniMap?(): void;
|
||||||
initViewPort?(): void;
|
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
onCameraChanged(callback: (viewport: IViewport) => void): void;
|
onCameraChanged(callback: (viewport: IViewport) => void): void;
|
||||||
// init map
|
// init map
|
||||||
addMarkerContainer(): void;
|
addMarkerContainer(): void;
|
||||||
getMarkerContainer(): HTMLElement;
|
getMarkerContainer(): HTMLElement;
|
||||||
|
getOverlayContainer(): HTMLElement | undefined;
|
||||||
// MapEvent // 定义事件类型
|
// MapEvent // 定义事件类型
|
||||||
|
|
||||||
on(type: string, handler: (...args: any[]) => void): void;
|
on(type: string, handler: (...args: any[]) => void): void;
|
||||||
|
@ -89,6 +89,7 @@ export interface IMapService<RawMap = {}> {
|
||||||
setZoom(zoom: number): void;
|
setZoom(zoom: number): void;
|
||||||
setMapStyle(style: any): void;
|
setMapStyle(style: any): void;
|
||||||
setMapStatus(option: Partial<IStatusOptions>): void;
|
setMapStatus(option: Partial<IStatusOptions>): void;
|
||||||
|
updateView(viewOption:Partial<IMapCamera>):void // 更新地图视野
|
||||||
|
|
||||||
// coordinates methods
|
// coordinates methods
|
||||||
meterToCoord(center: number[], lnglat: number[]): number;
|
meterToCoord(center: number[], lnglat: number[]): number;
|
||||||
|
@ -129,7 +130,6 @@ export interface IEarthService<RawMap = {}> {
|
||||||
bgColor: string;
|
bgColor: string;
|
||||||
setBgColor(color: string): void;
|
setBgColor(color: string): void;
|
||||||
init(): void;
|
init(): void;
|
||||||
initViewPort?(): void;
|
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
onCameraChanged(callback: (viewport: IViewport) => void): void;
|
onCameraChanged(callback: (viewport: IViewport) => void): void;
|
||||||
// init map
|
// init map
|
||||||
|
@ -267,6 +267,8 @@ export interface IMapConfig<RawMap = {}> {
|
||||||
|
|
||||||
offsetZoom?: number;
|
offsetZoom?: number;
|
||||||
|
|
||||||
|
interactive: boolean;//
|
||||||
|
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { ISceneConfig } from '../config/IConfigService';
|
import { ISceneConfig } from '../config/IConfigService';
|
||||||
import { ILayer } from '../layer/ILayerService';
|
import { ILayer } from '../layer/ILayerService';
|
||||||
import { IMapConfig } from '../map/IMapService';
|
|
||||||
import { IRenderConfig } from '../renderer/IRendererService';
|
|
||||||
|
|
||||||
export interface ISceneService {
|
export interface ISceneService {
|
||||||
destroyed: boolean;
|
destroyed: boolean;
|
||||||
|
@ -12,8 +10,8 @@ export interface ISceneService {
|
||||||
once(type: string, handle: (...args: any[]) => void): void;
|
once(type: string, handle: (...args: any[]) => void): void;
|
||||||
off(type: string, handle: (...args: any[]) => void): void;
|
off(type: string, handle: (...args: any[]) => void): void;
|
||||||
removeAllListeners(event?: string): this;
|
removeAllListeners(event?: string): this;
|
||||||
init(config: IMapConfig & IRenderConfig): void;
|
init(config: ISceneConfig): void;
|
||||||
initMiniScene(config: IMapConfig & IRenderConfig): void;
|
initMiniScene(config: ISceneConfig): void;
|
||||||
addLayer(layer: ILayer): void;
|
addLayer(layer: ILayer): void;
|
||||||
addMask(mask: ILayer): void;
|
addMask(mask: ILayer): void;
|
||||||
getSceneConfig(): Partial<ISceneConfig>;
|
getSceneConfig(): Partial<ISceneConfig>;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { AsyncParallelHook } from '@antv/async-hook';
|
import { AsyncSeriesHook } from '@antv/async-hook';
|
||||||
import { $window, DOM } from '@antv/l7-utils';
|
import { $window, DOM } from '@antv/l7-utils';
|
||||||
import elementResizeEvent, { unbind } from 'element-resize-event';
|
import elementResizeEvent, { unbind } from 'element-resize-event';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
@ -106,7 +106,7 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
private markerContainer: HTMLElement;
|
private markerContainer: HTMLElement;
|
||||||
|
|
||||||
private hooks: {
|
private hooks: {
|
||||||
init: AsyncParallelHook;
|
init: AsyncSeriesHook;
|
||||||
};
|
};
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
|
@ -119,7 +119,7 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
* 2. initRenderer:初始化渲染引擎
|
* 2. initRenderer:初始化渲染引擎
|
||||||
* 3. initWorker:初始化 Worker
|
* 3. initWorker:初始化 Worker
|
||||||
*/
|
*/
|
||||||
init: new AsyncParallelHook(),
|
init: new AsyncSeriesHook(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,31 +144,15 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
this.map.onCameraChanged((viewport: IViewport) => {
|
this.map.onCameraChanged((viewport: IViewport) => {
|
||||||
this.cameraService.init();
|
this.cameraService.init();
|
||||||
this.cameraService.update(viewport);
|
this.cameraService.update(viewport);
|
||||||
if (this.map.version !== 'GAODE2.x') {
|
|
||||||
// not amap2
|
|
||||||
resolve();
|
resolve();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.map.version !== 'GAODE2.x') {
|
|
||||||
// not amap2
|
|
||||||
this.map.init();
|
this.map.init();
|
||||||
} else {
|
|
||||||
// amap2
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.map.version === 'GAODE2.x' && this.map.initViewPort) {
|
|
||||||
// amap2
|
|
||||||
await this.map.init();
|
|
||||||
this.map.initViewPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新绑定非首次相机更新事件
|
// 重新绑定非首次相机更新事件
|
||||||
this.map.onCameraChanged(this.handleMapCameraChanged);
|
this.map.onCameraChanged(this.handleMapCameraChanged);
|
||||||
this.map.addMarkerContainer();
|
this.map.addMarkerContainer();
|
||||||
|
|
||||||
// 初始化未加载的marker;
|
// 初始化未加载的marker;
|
||||||
this.markerService.addMarkers();
|
this.markerService.addMarkers();
|
||||||
this.markerService.addMarkerLayers();
|
this.markerService.addMarkerLayers();
|
||||||
|
@ -185,16 +169,23 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
* 初始化渲染引擎
|
* 初始化渲染引擎
|
||||||
*/
|
*/
|
||||||
this.hooks.init.tapPromise('initRenderer', async () => {
|
this.hooks.init.tapPromise('initRenderer', async () => {
|
||||||
// 创建底图之上的 container
|
const renderContainer = this.map.getOverlayContainer();
|
||||||
const $container = createRendererContainer(
|
|
||||||
|
if(renderContainer) {
|
||||||
|
this.$container = renderContainer as HTMLDivElement;
|
||||||
|
} else {
|
||||||
|
this.$container = createRendererContainer(
|
||||||
this.configService.getSceneConfig(this.id).id || '',
|
this.configService.getSceneConfig(this.id).id || '',
|
||||||
);
|
);
|
||||||
|
|
||||||
// 添加marker container;
|
}
|
||||||
this.$container = $container;
|
|
||||||
|
|
||||||
if ($container) {
|
|
||||||
this.canvas = DOM.create('canvas', '', $container) as HTMLCanvasElement;
|
// 创建底图之上的 container
|
||||||
|
|
||||||
|
|
||||||
|
if (this.$container) {
|
||||||
|
this.canvas = DOM.create('canvas', '', this.$container) as HTMLCanvasElement;
|
||||||
this.setCanvas();
|
this.setCanvas();
|
||||||
await this.rendererService.init(
|
await this.rendererService.init(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -321,7 +312,7 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
// 还未初始化完成需要等待
|
// 还未初始化完成需要等待
|
||||||
|
|
||||||
await this.initPromise;
|
await this.initPromise; // 初始化地图和渲染
|
||||||
if (this.destroyed) {
|
if (this.destroyed) {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
|
@ -336,6 +327,7 @@ export default class Scene extends EventEmitter implements ISceneService {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 初始化 marker 容器,可以放到 map 初始化方法中?
|
// FIXME: 初始化 marker 容器,可以放到 map 初始化方法中?
|
||||||
this.layerService.initLayers();
|
this.layerService.initLayers();
|
||||||
this.controlService.addControls();
|
this.controlService.addControls();
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
declare module 'l7hammerjs';
|
declare module 'l7hammerjs';
|
||||||
declare module 'l7-tiny-sdf';
|
declare module 'l7-tiny-sdf';
|
||||||
declare module '@antv/l7-maps';
|
|
|
@ -26,7 +26,7 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/async-hook": "^2.1.0",
|
"@antv/async-hook": "^2.2.2",
|
||||||
"@antv/l7-core": "2.9.26",
|
"@antv/l7-core": "2.9.26",
|
||||||
"@antv/l7-maps": "2.9.26",
|
"@antv/l7-maps": "2.9.26",
|
||||||
"@antv/l7-source": "2.9.26",
|
"@antv/l7-source": "2.9.26",
|
||||||
|
|
|
@ -208,9 +208,6 @@ export default class LineModel extends BaseModel {
|
||||||
size: 2,
|
size: 2,
|
||||||
update: (
|
update: (
|
||||||
feature: IEncodeFeature,
|
feature: IEncodeFeature,
|
||||||
featureIdx: number,
|
|
||||||
vertex: number[],
|
|
||||||
attributeIdx: number,
|
|
||||||
) => {
|
) => {
|
||||||
const { size = 1 } = feature;
|
const { size = 1 } = feature;
|
||||||
return Array.isArray(size) ? [size[0], size[1]] : [size as number, 0];
|
return Array.isArray(size) ? [size[0], size[1]] : [size as number, 0];
|
||||||
|
|
|
@ -151,7 +151,6 @@ export default class LineWallModel extends BaseModel {
|
||||||
feature: IEncodeFeature,
|
feature: IEncodeFeature,
|
||||||
featureIdx: number,
|
featureIdx: number,
|
||||||
vertex: number[],
|
vertex: number[],
|
||||||
attributeIdx: number,
|
|
||||||
) => {
|
) => {
|
||||||
return [vertex[3]];
|
return [vertex[3]];
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { IParseDataItem } from '@antv/l7-core';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Martini from '@mapbox/martini';
|
import Martini from '@mapbox/martini';
|
||||||
export function RasterTriangulation(parserData: IParseDataItem) {
|
export function RasterTriangulation(parserData: IParseDataItem) {
|
||||||
const { coordinates, data, min, max, width, height } = parserData;
|
const { data,width, height } = parserData;
|
||||||
const maxlength = Math.max(width, height);
|
const maxlength = Math.max(width, height);
|
||||||
const gridSize = Math.pow(2, Math.ceil(Math.log2(maxlength))) + 1;
|
const gridSize = Math.pow(2, Math.ceil(Math.log2(maxlength))) + 1;
|
||||||
const terrain = new Float32Array(gridSize * gridSize);
|
const terrain = new Float32Array(gridSize * gridSize);
|
||||||
|
|
|
@ -115,10 +115,7 @@ export default class Viewport implements IViewport {
|
||||||
/**
|
/**
|
||||||
* P20 坐标系,固定 scale
|
* P20 坐标系,固定 scale
|
||||||
*/
|
*/
|
||||||
public projectFlat(
|
public projectFlat(lngLat: [number, number]): [number, number] {
|
||||||
lngLat: [number, number],
|
|
||||||
scale?: number | undefined,
|
|
||||||
): [number, number] {
|
|
||||||
const maxs = 85.0511287798;
|
const maxs = 85.0511287798;
|
||||||
const lat = Math.max(Math.min(maxs, lngLat[1]), -maxs);
|
const lat = Math.max(Math.min(maxs, lngLat[1]), -maxs);
|
||||||
// tslint:disable-next-line:no-bitwise
|
// tslint:disable-next-line:no-bitwise
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IAMapInstance } from '../../typings/index';
|
import { IAMapInstance } from '../../typings/index';
|
||||||
import BaseMapWrapper from '../BaseMapWrapper';
|
import BaseMapWrapper from '../utils/BaseMapWrapper';
|
||||||
import AMapService from './map';
|
import AMapService from './map';
|
||||||
|
|
||||||
export default class AMapWrapper extends BaseMapWrapper<
|
export default class AMapWrapper extends BaseMapWrapper<
|
||||||
|
|
|
@ -3,42 +3,25 @@
|
||||||
*/
|
*/
|
||||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||||
import {
|
import {
|
||||||
Bounds,
|
|
||||||
CoordinateSystem,
|
CoordinateSystem,
|
||||||
ICameraOptions,
|
|
||||||
ICoordinateSystemService,
|
|
||||||
IGlobalConfigService,
|
|
||||||
ILngLat,
|
|
||||||
IMapConfig,
|
|
||||||
IMapService,
|
IMapService,
|
||||||
IMercator,
|
|
||||||
IPoint,
|
|
||||||
IStatusOptions,
|
|
||||||
IViewport,
|
IViewport,
|
||||||
MapServiceEvent,
|
IMapCamera,
|
||||||
TYPES,
|
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { DOM } from '@antv/l7-utils';
|
|
||||||
import { mat4, vec3 } from 'gl-matrix';
|
import { mat4, vec3 } from 'gl-matrix';
|
||||||
import { inject, injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { IAMapEvent, IAMapInstance } from '../../typings/index';
|
import { IAMapEvent, IAMapInstance } from '../../typings/index';
|
||||||
import { ISimpleMapCoord, SimpleMapCoord } from '../simpleMapCoord';
|
|
||||||
import { toPaddingOptions } from '../utils';
|
|
||||||
import { Version } from '../version';
|
import { Version } from '../version';
|
||||||
import './logo.css';
|
|
||||||
import { MapTheme } from './theme';
|
|
||||||
import Viewport from './Viewport';
|
import Viewport from './Viewport';
|
||||||
let mapdivCount = 0;
|
import AMapBaseService from '../utils/amap/AMapBaseService';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.forceWebGL = true;
|
window.forceWebGL = true;
|
||||||
|
|
||||||
const AMAP_API_KEY: string = '15cd8a57710d40c9b7c0e3cc120f1200';
|
const AMAP_API_KEY: string = '15cd8a57710d40c9b7c0e3cc120f1200';
|
||||||
const AMAP_VERSION: string = '1.4.15';
|
const AMAP_VERSION: string = '1.4.15';
|
||||||
/**
|
|
||||||
* 确保多个场景只引入一个高德地图脚本
|
|
||||||
*/
|
|
||||||
const AMAP_SCRIPT_ID: string = 'amap-script';
|
|
||||||
/**
|
/**
|
||||||
* 高德地图脚本是否加载完毕
|
* 高德地图脚本是否加载完毕
|
||||||
*/
|
*/
|
||||||
|
@ -53,263 +36,16 @@ const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; // 暂时关闭 fix 统一不同坐标
|
||||||
* AMapService
|
* AMapService
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class AMapService
|
export default class AMapService extends AMapBaseService
|
||||||
implements IMapService<AMap.Map & IAMapInstance> {
|
implements IMapService<AMap.Map & IAMapInstance> {
|
||||||
public version: string = Version['GAODE1.x'];
|
public version: string = Version['GAODE1.x'];
|
||||||
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
protected viewport: IViewport;
|
||||||
/**
|
|
||||||
* 原始地图实例
|
|
||||||
*/
|
|
||||||
public map: AMap.Map & IAMapInstance;
|
|
||||||
|
|
||||||
// 背景色
|
|
||||||
public bgColor: string = 'rgba(0, 0, 0, 0)';
|
|
||||||
|
|
||||||
@inject(TYPES.IGlobalConfigService)
|
|
||||||
private readonly configService: IGlobalConfigService;
|
|
||||||
|
|
||||||
@inject(TYPES.MapConfig)
|
|
||||||
private readonly config: Partial<IMapConfig>;
|
|
||||||
|
|
||||||
@inject(TYPES.ICoordinateSystemService)
|
|
||||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
|
||||||
|
|
||||||
@inject(TYPES.IEventEmitter)
|
|
||||||
private eventEmitter: any;
|
|
||||||
|
|
||||||
private markerContainer: HTMLElement;
|
|
||||||
private $mapContainer: HTMLElement | null;
|
|
||||||
|
|
||||||
private viewport: Viewport;
|
|
||||||
|
|
||||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
|
||||||
public setBgColor(color: string) {
|
|
||||||
this.bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public addMarkerContainer(): void {
|
|
||||||
const mapContainer = this.map.getContainer();
|
|
||||||
if (mapContainer !== null) {
|
|
||||||
const amap = mapContainer.getElementsByClassName(
|
|
||||||
'amap-maps',
|
|
||||||
)[0] as HTMLElement;
|
|
||||||
this.markerContainer = DOM.create('div', 'l7-marker-container', amap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public getMarkerContainer(): HTMLElement {
|
|
||||||
return this.markerContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map event
|
|
||||||
public on(type: string, handler: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.on(type, handler);
|
|
||||||
} else {
|
|
||||||
this.map.on(type, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public off(type: string, handler: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.off(type, handler);
|
|
||||||
} else {
|
|
||||||
this.map.off(type, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getContainer(): HTMLElement | null {
|
|
||||||
return this.map.getContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapCanvasContainer(): HTMLElement {
|
|
||||||
return this.map
|
|
||||||
.getContainer()
|
|
||||||
?.getElementsByClassName('amap-maps')[0] as HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSize(): [number, number] {
|
|
||||||
const size = this.map.getSize();
|
|
||||||
return [size.getWidth(), size.getHeight()];
|
|
||||||
}
|
|
||||||
|
|
||||||
public getType() {
|
|
||||||
return 'amap';
|
|
||||||
}
|
|
||||||
public getZoom(): number {
|
|
||||||
// 统一返回 Mapbox 缩放等级
|
|
||||||
return this.map.getZoom() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoom(zoom: number): void {
|
|
||||||
// 统一设置 Mapbox 缩放等级
|
|
||||||
return this.map.setZoom(zoom + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCenter(options?: ICameraOptions): ILngLat {
|
|
||||||
if (options?.padding) {
|
|
||||||
const originCenter = this.getCenter();
|
|
||||||
const [w, h] = this.getSize();
|
|
||||||
const padding = toPaddingOptions(options.padding);
|
|
||||||
const px = this.lngLatToPixel([originCenter.lng, originCenter.lat]);
|
|
||||||
const offsetPx = [
|
|
||||||
(padding.right - padding.left) / 2,
|
|
||||||
(padding.bottom - padding.top) / 2,
|
|
||||||
];
|
|
||||||
|
|
||||||
const newCenter = this.pixelToLngLat([
|
|
||||||
px.x - offsetPx[0],
|
|
||||||
px.y - offsetPx[1],
|
|
||||||
]);
|
|
||||||
return newCenter;
|
|
||||||
}
|
|
||||||
const center = this.map.getCenter();
|
|
||||||
return {
|
|
||||||
lng: center.getLng(),
|
|
||||||
lat: center.getLat(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public setCenter(lnglat: [number, number], options?: ICameraOptions): void {
|
|
||||||
if (options?.padding) {
|
|
||||||
const padding = toPaddingOptions(options.padding);
|
|
||||||
const px = this.lngLatToPixel(lnglat);
|
|
||||||
const offsetPx = [
|
|
||||||
(padding.right - padding.left) / 2,
|
|
||||||
(padding.bottom - padding.top) / 2,
|
|
||||||
];
|
|
||||||
const newCenter = this.pixelToLngLat([
|
|
||||||
px.x + offsetPx[0],
|
|
||||||
px.y + offsetPx[1],
|
|
||||||
]);
|
|
||||||
this.map.setCenter([newCenter.lng, newCenter.lat]);
|
|
||||||
} else {
|
|
||||||
this.map.setCenter(lnglat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public getPitch(): number {
|
|
||||||
return this.map.getPitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRotation(): number {
|
|
||||||
// 统一返回逆时针旋转角度
|
|
||||||
return 360 - this.map.getRotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBounds(): Bounds {
|
|
||||||
// @ts-ignore
|
|
||||||
const amapBound = this.map.getBounds().toBounds();
|
|
||||||
const NE = amapBound.getNorthEast();
|
|
||||||
const SW = amapBound.getSouthWest();
|
|
||||||
const center = this.getCenter();
|
|
||||||
const maxlng =
|
|
||||||
center.lng > NE.getLng() || center.lng < SW.getLng()
|
|
||||||
? 180 - NE.getLng()
|
|
||||||
: NE.getLng();
|
|
||||||
const minlng = center.lng < SW.getLng() ? SW.getLng() - 180 : SW.getLng();
|
|
||||||
// 兼容 Mapbox,统一返回西南、东北
|
|
||||||
return [
|
|
||||||
[minlng, SW.getLat()],
|
|
||||||
[maxlng, NE.getLat()],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMinZoom(): number {
|
|
||||||
const zooms = this.map.get('zooms') as [number, number];
|
|
||||||
return zooms[0] - 1;
|
|
||||||
}
|
|
||||||
public getMaxZoom(): number {
|
|
||||||
const zooms = this.map.get('zooms') as [number, number];
|
|
||||||
return zooms[1] - 1;
|
|
||||||
}
|
|
||||||
public setRotation(rotation: number): void {
|
|
||||||
return this.map.setRotation(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setPitch(pitch: number) {
|
|
||||||
return this.map.setPitch(pitch);
|
|
||||||
}
|
|
||||||
public zoomIn(): void {
|
|
||||||
this.map.zoomIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
public zoomOut(): void {
|
|
||||||
this.map.zoomOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
public panTo(p: [number, number]): void {
|
|
||||||
this.map.panTo(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panBy(x: number = 0, y: number = 0): void {
|
|
||||||
this.map.panBy(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public fitBounds(extent: Bounds): void {
|
|
||||||
this.map.setBounds(
|
|
||||||
new AMap.Bounds([extent[0][0], extent[0][1], extent[1][0], extent[1][1]]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
|
||||||
this.map.setZoomAndCenter(zoom + 1, center);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStyle(style: string): void {
|
|
||||||
this.map.setMapStyle(this.getMapStyle(style));
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStatus(option: Partial<IStatusOptions>): void {
|
|
||||||
this.map.setStatus(option);
|
|
||||||
}
|
|
||||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
const lngLat = this.map.pixelToLngLat(new AMap.Pixel(pixel[0], pixel[1]));
|
|
||||||
return { lng: lngLat.getLng(), lat: lngLat.getLat() };
|
|
||||||
}
|
|
||||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
|
||||||
const p = this.map.lnglatToPixel(new AMap.LngLat(lnglat[0], lnglat[1]));
|
|
||||||
return {
|
|
||||||
x: p.getX(),
|
|
||||||
y: p.getY(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
const ll = new AMap.Pixel(pixel[0], pixel[1]);
|
|
||||||
const lngLat = this.map.containerToLngLat(ll);
|
|
||||||
return {
|
|
||||||
lng: lngLat?.getLng(),
|
|
||||||
lat: lngLat?.getLat(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
|
||||||
const ll = new AMap.LngLat(lnglat[0], lnglat[1]);
|
|
||||||
const pixel = this.map.lngLatToContainer(ll);
|
|
||||||
return {
|
|
||||||
x: pixel.getX(),
|
|
||||||
y: pixel.getY(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToCoord(lnglat: [number, number]): any {
|
|
||||||
// @ts-ignore
|
|
||||||
const { x, y } = this.map.lngLatToGeodeticCoord(lnglat);
|
|
||||||
return [x, -y];
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToMercator(
|
|
||||||
lnglat: [number, number],
|
|
||||||
altitude: number,
|
|
||||||
): IMercator {
|
|
||||||
return {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public getModelMatrix(
|
public getModelMatrix(
|
||||||
lnglat: [number, number],
|
lnglat: [number, number],
|
||||||
altitude: number,
|
altitude: number,
|
||||||
rotate: [number, number, number],
|
rotate: [number, number, number],
|
||||||
scale: [number, number, number] = [1, 1, 1],
|
scale: [number, number, number] = [1, 1, 1],
|
||||||
origin: IMercator = { x: 0, y: 0, z: 0 },
|
|
||||||
): number[] {
|
): number[] {
|
||||||
const flat = this.viewport.projectFlat(lnglat);
|
const flat = this.viewport.projectFlat(lnglat);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -356,7 +92,7 @@ export default class AMapService
|
||||||
resolve();
|
resolve();
|
||||||
}, 30);
|
}, 30);
|
||||||
} else {
|
} else {
|
||||||
this.$mapContainer = this.creatAmapContainer(
|
this.$mapContainer = this.creatMapContainer(
|
||||||
id as string | HTMLDivElement,
|
id as string | HTMLDivElement,
|
||||||
);
|
);
|
||||||
const mapConstructorOptions = {
|
const mapConstructorOptions = {
|
||||||
|
@ -436,6 +172,12 @@ export default class AMapService
|
||||||
return coordDis / meterDis;
|
return coordDis / meterDis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateView(viewOption: Partial<IMapCamera>): void {}
|
||||||
|
|
||||||
|
public getOverlayContainer(): HTMLElement | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
public exportMap(type: 'jpg' | 'png'): string {
|
public exportMap(type: 'jpg' | 'png'): string {
|
||||||
const renderCanvas = this.getContainer()?.getElementsByClassName(
|
const renderCanvas = this.getContainer()?.getElementsByClassName(
|
||||||
'amap-layer',
|
'amap-layer',
|
||||||
|
@ -447,41 +189,11 @@ export default class AMapService
|
||||||
return layersPng;
|
return layersPng;
|
||||||
}
|
}
|
||||||
|
|
||||||
public emit(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.emit(name, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public once(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.once(name, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy() {
|
|
||||||
this.map.destroy();
|
|
||||||
|
|
||||||
// TODO: 销毁地图可视化层的容器
|
|
||||||
this.$mapContainer?.parentNode?.removeChild(this.$mapContainer);
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
delete window.initAMap;
|
|
||||||
const $jsapi = document.getElementById(AMAP_SCRIPT_ID);
|
|
||||||
if ($jsapi) {
|
|
||||||
document.head.removeChild($jsapi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapContainer() {
|
|
||||||
return this.$mapContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||||
this.cameraChangedCallback = callback;
|
this.cameraChangedCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleAfterMapChange() {
|
protected handleCameraChanged = (e: IAMapEvent): void => {
|
||||||
this.emit('mapAfterFrameChange');
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleCameraChanged = (e: IAMapEvent): void => {
|
|
||||||
const {
|
const {
|
||||||
fov,
|
fov,
|
||||||
near,
|
near,
|
||||||
|
@ -497,11 +209,6 @@ export default class AMapService
|
||||||
this.emit('mapchange');
|
this.emit('mapchange');
|
||||||
|
|
||||||
if (this.cameraChangedCallback) {
|
if (this.cameraChangedCallback) {
|
||||||
// resync viewport
|
|
||||||
// console.log('cameraHeight', height)
|
|
||||||
// console.log('pitch', pitch)
|
|
||||||
// console.log('rotation', rotation)
|
|
||||||
// console.log('zoom', this.map.getZoom())
|
|
||||||
this.viewport.syncWithMapCamera({
|
this.viewport.syncWithMapCamera({
|
||||||
aspect,
|
aspect,
|
||||||
// AMap 定义 rotation 为顺时针方向,而 Mapbox 为逆时针
|
// AMap 定义 rotation 为顺时针方向,而 Mapbox 为逆时针
|
||||||
|
@ -530,24 +237,4 @@ export default class AMapService
|
||||||
this.cameraChangedCallback(this.viewport);
|
this.cameraChangedCallback(this.viewport);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private getMapStyle(name: string): string {
|
|
||||||
return MapTheme[name] ? MapTheme[name] : name;
|
|
||||||
}
|
|
||||||
private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
let $wrapper = id as HTMLDivElement;
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
$wrapper = document.getElementById(id) as HTMLDivElement;
|
|
||||||
}
|
|
||||||
const $amapdiv = document.createElement('div');
|
|
||||||
$amapdiv.style.cssText += `
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
$amapdiv.id = 'l7_amap_div' + mapdivCount++;
|
|
||||||
$wrapper.appendChild($amapdiv);
|
|
||||||
return $amapdiv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IAMapInstance } from '../../typings/index';
|
import { IAMapInstance } from '../../typings/index';
|
||||||
import BaseMapWrapper from '../BaseMapWrapper';
|
import BaseMapWrapper from '../utils/BaseMapWrapper';
|
||||||
import AMapService from './map';
|
import AMapService from './map';
|
||||||
|
|
||||||
export default class AMapWrapper2 extends BaseMapWrapper<
|
export default class AMapWrapper2 extends BaseMapWrapper<
|
||||||
|
|
|
@ -5,32 +5,21 @@ import AMapLoader from '@amap/amap-jsapi-loader';
|
||||||
import {
|
import {
|
||||||
Bounds,
|
Bounds,
|
||||||
CoordinateSystem,
|
CoordinateSystem,
|
||||||
ICameraOptions,
|
|
||||||
ICoordinateSystemService,
|
|
||||||
IGlobalConfigService,
|
|
||||||
ILngLat,
|
|
||||||
IMapConfig,
|
|
||||||
IMapService,
|
|
||||||
IMercator,
|
|
||||||
IPoint,
|
IPoint,
|
||||||
IStatusOptions,
|
|
||||||
IViewport,
|
IViewport,
|
||||||
MapServiceEvent,
|
IMapCamera,
|
||||||
TYPES,
|
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { amap2Project, DOM } from '@antv/l7-utils';
|
import { amap2Project, DOM } from '@antv/l7-utils';
|
||||||
import { mat4, vec2, vec3 } from 'gl-matrix';
|
import { mat4, vec2, vec3 } from 'gl-matrix';
|
||||||
import { inject, injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { IAMapInstance } from '../../typings/index';
|
import { IAMapInstance } from '../../typings/index';
|
||||||
import { SimpleMapCoord } from '../simpleMapCoord';
|
|
||||||
import { toPaddingOptions } from '../utils';
|
|
||||||
import { Version } from '../version';
|
import { Version } from '../version';
|
||||||
import './logo.css';
|
import './logo.css';
|
||||||
import { MapTheme } from './theme';
|
import { MapTheme } from './theme';
|
||||||
import Viewport from './Viewport';
|
import Viewport from './Viewport';
|
||||||
|
import AMapBaseService from '../utils/amap/AMapBaseService';
|
||||||
|
|
||||||
let mapdivCount = 0;
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.forceWebGL = true;
|
window.forceWebGL = true;
|
||||||
|
|
||||||
|
@ -38,10 +27,7 @@ window.forceWebGL = true;
|
||||||
const AMAP_API_KEY: string = 'ff533602d57df6f8ab3b0fea226ae52f';
|
const AMAP_API_KEY: string = 'ff533602d57df6f8ab3b0fea226ae52f';
|
||||||
// const AMAP_VERSION: string = '1.4.15';
|
// const AMAP_VERSION: string = '1.4.15';
|
||||||
const AMAP_VERSION: string = '2.0.5';
|
const AMAP_VERSION: string = '2.0.5';
|
||||||
/**
|
|
||||||
* 确保多个场景只引入一个高德地图脚本
|
|
||||||
*/
|
|
||||||
const AMAP_SCRIPT_ID: string = 'amap-script';
|
|
||||||
/**
|
/**
|
||||||
* 高德地图脚本是否加载完毕
|
* 高德地图脚本是否加载完毕
|
||||||
*/
|
*/
|
||||||
|
@ -55,14 +41,8 @@ let pendingResolveQueue: Array<() => void> = [];
|
||||||
* AMapService
|
* AMapService
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class AMapService
|
export default class AMapService extends AMapBaseService {
|
||||||
implements IMapService<AMap.Map & IAMapInstance> {
|
|
||||||
public version: string = Version['GAODE2.x'];
|
public version: string = Version['GAODE2.x'];
|
||||||
public simpleMapCoord: SimpleMapCoord = new SimpleMapCoord();
|
|
||||||
/**
|
|
||||||
* 原始地图实例
|
|
||||||
*/
|
|
||||||
public map: AMap.Map & IAMapInstance;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于 customCooords 数据的计算
|
* 用于 customCooords 数据的计算
|
||||||
|
@ -70,30 +50,7 @@ export default class AMapService
|
||||||
public sceneCenter!: [number, number]; // 一般使用用户数据的第一个
|
public sceneCenter!: [number, number]; // 一般使用用户数据的第一个
|
||||||
public sceneCenterMKT!: [number, number]; // 莫卡托
|
public sceneCenterMKT!: [number, number]; // 莫卡托
|
||||||
|
|
||||||
// 背景色
|
protected viewport: Viewport;
|
||||||
public bgColor: string = 'rgba(0, 0, 0, 0)';
|
|
||||||
|
|
||||||
@inject(TYPES.IGlobalConfigService)
|
|
||||||
private readonly configService: IGlobalConfigService;
|
|
||||||
|
|
||||||
@inject(TYPES.MapConfig)
|
|
||||||
private readonly config: Partial<IMapConfig>;
|
|
||||||
|
|
||||||
@inject(TYPES.ICoordinateSystemService)
|
|
||||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
|
||||||
|
|
||||||
@inject(TYPES.IEventEmitter)
|
|
||||||
private eventEmitter: any;
|
|
||||||
|
|
||||||
private markerContainer: HTMLElement;
|
|
||||||
private $mapContainer: HTMLElement | null;
|
|
||||||
|
|
||||||
private viewport: Viewport;
|
|
||||||
|
|
||||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
|
||||||
public setBgColor(color: string) {
|
|
||||||
this.bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置数据的绘制中心 高德2.0
|
* 设置数据的绘制中心 高德2.0
|
||||||
|
@ -182,116 +139,24 @@ export default class AMapService
|
||||||
// TODO: amap2 的 amap-maps 新增 z-index=0; 样式,让 marker 中 zIndex 失效
|
// TODO: amap2 的 amap-maps 新增 z-index=0; 样式,让 marker 中 zIndex 失效
|
||||||
amap.style.zIndex = 'auto';
|
amap.style.zIndex = 'auto';
|
||||||
this.markerContainer = DOM.create('div', 'l7-marker-container2', amap);
|
this.markerContainer = DOM.create('div', 'l7-marker-container2', amap);
|
||||||
// this.markerContainer = DOM.create(
|
|
||||||
// 'div',
|
|
||||||
// 'l7-marker-container2',
|
|
||||||
// mapContainer,
|
|
||||||
// );
|
|
||||||
// this.markerContainer = mapContainer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public getMarkerContainer(): HTMLElement {
|
|
||||||
return this.markerContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map event
|
|
||||||
public on(type: string, handler: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.on(type, handler);
|
|
||||||
} else {
|
|
||||||
this.map.on(type, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public off(type: string, handler: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.off(type, handler);
|
|
||||||
} else {
|
|
||||||
this.map.off(type, handler);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContainer(): HTMLElement | null {
|
public updateView(_viewOption: Partial<IMapCamera>): void {}
|
||||||
return this.map.getContainer();
|
|
||||||
|
public getOverlayContainer(): HTMLElement | undefined {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMapCanvasContainer(): HTMLElement {
|
protected getMapStyle(name: string): string {
|
||||||
return this.map
|
return MapTheme[name] ? MapTheme[name] : name;
|
||||||
.getContainer()
|
|
||||||
?.getElementsByClassName('amap-maps')[0] as HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSize(): [number, number] {
|
|
||||||
const size = this.map.getSize();
|
|
||||||
return [size.getWidth(), size.getHeight()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getType() {
|
public getType() {
|
||||||
return 'amap2';
|
return 'amap2';
|
||||||
}
|
}
|
||||||
public getZoom(): number {
|
|
||||||
// 统一返回 Mapbox 缩放等级
|
|
||||||
return this.map.getZoom() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoom(zoom: number): void {
|
|
||||||
// 统一设置 Mapbox 缩放等级
|
|
||||||
return this.map.setZoom(zoom + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCenter(options?: ICameraOptions): ILngLat {
|
|
||||||
if (options?.padding) {
|
|
||||||
const originCenter = this.getCenter();
|
|
||||||
const [w, h] = this.getSize();
|
|
||||||
const padding = toPaddingOptions(options.padding);
|
|
||||||
const px = this.lngLatToPixel([originCenter.lng, originCenter.lat]);
|
|
||||||
const offsetPx = [
|
|
||||||
(padding.right - padding.left) / 2,
|
|
||||||
(padding.bottom - padding.top) / 2,
|
|
||||||
];
|
|
||||||
|
|
||||||
const newCenter = this.pixelToLngLat([
|
|
||||||
px.x - offsetPx[0],
|
|
||||||
px.y - offsetPx[1],
|
|
||||||
]);
|
|
||||||
return newCenter;
|
|
||||||
}
|
|
||||||
const center = this.map.getCenter();
|
|
||||||
return {
|
|
||||||
lng: center.getLng(),
|
|
||||||
lat: center.getLat(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public setCenter(lnglat: [number, number], options?: ICameraOptions): void {
|
|
||||||
if (options?.padding) {
|
|
||||||
const padding = toPaddingOptions(options.padding);
|
|
||||||
const px = this.lngLatToPixel(lnglat);
|
|
||||||
const offsetPx = [
|
|
||||||
(padding.right - padding.left) / 2,
|
|
||||||
(padding.bottom - padding.top) / 2,
|
|
||||||
];
|
|
||||||
const newCenter = this.pixelToLngLat([
|
|
||||||
px.x + offsetPx[0],
|
|
||||||
px.y + offsetPx[1],
|
|
||||||
]);
|
|
||||||
this.map.setCenter([newCenter.lng, newCenter.lat]);
|
|
||||||
} else {
|
|
||||||
this.map.setCenter(lnglat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public getPitch(): number {
|
|
||||||
return this.map.getPitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRotation(): number {
|
|
||||||
// 统一返回逆时针旋转角度
|
|
||||||
return 360 - this.map.getRotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBounds(): Bounds {
|
public getBounds(): Bounds {
|
||||||
// @ts-ignore
|
|
||||||
// const amapBound = this.map.getBounds().toBounds();
|
|
||||||
// const NE = amapBound.getNorthEast();
|
|
||||||
// const SW = amapBound.getSouthWest();
|
|
||||||
const bounds = this.map.getBounds();
|
const bounds = this.map.getBounds();
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -323,61 +188,7 @@ export default class AMapService
|
||||||
const zooms = this.map.getZooms() as [number, number];
|
const zooms = this.map.getZooms() as [number, number];
|
||||||
return zooms[1] - 1;
|
return zooms[1] - 1;
|
||||||
}
|
}
|
||||||
public setRotation(rotation: number): void {
|
|
||||||
return this.map.setRotation(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setPitch(pitch: number) {
|
|
||||||
return this.map.setPitch(pitch);
|
|
||||||
}
|
|
||||||
public zoomIn(): void {
|
|
||||||
this.map.zoomIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
public zoomOut(): void {
|
|
||||||
this.map.zoomOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
public panTo(p: [number, number]): void {
|
|
||||||
this.map.panTo(p);
|
|
||||||
}
|
|
||||||
public panBy(x: number = 0, y: number = 0): void {
|
|
||||||
this.map.panBy(x, y);
|
|
||||||
}
|
|
||||||
public fitBounds(extent: Bounds): void {
|
|
||||||
this.map.setBounds(
|
|
||||||
new AMap.Bounds([extent[0][0], extent[0][1], extent[1][0], extent[1][1]]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
|
||||||
this.map.setZoomAndCenter(zoom + 1, center);
|
|
||||||
}
|
|
||||||
public setMapStyle(style: string): void {
|
|
||||||
this.map.setMapStyle(this.getMapStyle(style));
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStatus(option: Partial<IStatusOptions>): void {
|
|
||||||
this.map.setStatus(option);
|
|
||||||
}
|
|
||||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
const lngLat = this.map.pixelToLngLat(new AMap.Pixel(pixel[0], pixel[1]));
|
|
||||||
return { lng: lngLat.getLng(), lat: lngLat.getLat() };
|
|
||||||
}
|
|
||||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
|
||||||
const p = this.map.lnglatToPixel(new AMap.LngLat(lnglat[0], lnglat[1]));
|
|
||||||
return {
|
|
||||||
x: p.getX(),
|
|
||||||
y: p.getY(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
const ll = new AMap.Pixel(pixel[0], pixel[1]);
|
|
||||||
const lngLat = this.map.containerToLngLat(ll);
|
|
||||||
return {
|
|
||||||
lng: lngLat?.getLng(),
|
|
||||||
lat: lngLat?.getLat(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
||||||
const pixel = this.map.lngLatToContainer(lnglat);
|
const pixel = this.map.lngLatToContainer(lnglat);
|
||||||
return {
|
return {
|
||||||
|
@ -386,23 +197,11 @@ export default class AMapService
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public lngLatToMercator(
|
|
||||||
lnglat: [number, number],
|
|
||||||
altitude: number,
|
|
||||||
): IMercator {
|
|
||||||
return {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public getModelMatrix(
|
public getModelMatrix(
|
||||||
lnglat: [number, number],
|
lnglat: [number, number],
|
||||||
altitude: number,
|
altitude: number,
|
||||||
rotate: [number, number, number],
|
rotate: [number, number, number],
|
||||||
scale: [number, number, number] = [1, 1, 1],
|
scale: [number, number, number] = [1, 1, 1],
|
||||||
origin: IMercator = { x: 0, y: 0, z: 0 },
|
|
||||||
): number[] {
|
): number[] {
|
||||||
// const flat = this.viewport.projectFlat(lnglat);
|
// const flat = this.viewport.projectFlat(lnglat);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -465,7 +264,7 @@ export default class AMapService
|
||||||
resolve();
|
resolve();
|
||||||
}, 30);
|
}, 30);
|
||||||
} else {
|
} else {
|
||||||
this.$mapContainer = this.creatAmapContainer(
|
this.$mapContainer = this.creatMapContainer(
|
||||||
id as string | HTMLDivElement,
|
id as string | HTMLDivElement,
|
||||||
);
|
);
|
||||||
const mapConstructorOptions = {
|
const mapConstructorOptions = {
|
||||||
|
@ -527,55 +326,7 @@ export default class AMapService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
this.initViewPort();
|
||||||
|
|
||||||
public meterToCoord(center: [number, number], outer: [number, number]) {
|
|
||||||
// 统一根据经纬度来转化
|
|
||||||
// Tip: 实际米距离 unit meter
|
|
||||||
const meterDis = AMap.GeometryUtil.distance(
|
|
||||||
new AMap.LngLat(...center),
|
|
||||||
new AMap.LngLat(...outer),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Tip: 三维世界坐标距离
|
|
||||||
const [x1, y1] = this.lngLatToCoord(center);
|
|
||||||
const [x2, y2] = this.lngLatToCoord(outer);
|
|
||||||
const coordDis = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
|
||||||
|
|
||||||
return coordDis / meterDis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public exportMap(type: 'jpg' | 'png'): string {
|
|
||||||
const renderCanvas = this.getContainer()?.getElementsByClassName(
|
|
||||||
'amap-layer',
|
|
||||||
)[0] as HTMLCanvasElement;
|
|
||||||
const layersPng =
|
|
||||||
type === 'jpg'
|
|
||||||
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
|
||||||
: (renderCanvas?.toDataURL('image/png') as string);
|
|
||||||
return layersPng;
|
|
||||||
}
|
|
||||||
|
|
||||||
public emit(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.emit(name, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public once(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.once(name, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy() {
|
|
||||||
this.map.destroy();
|
|
||||||
|
|
||||||
// TODO: 销毁地图可视化层的容器
|
|
||||||
this.$mapContainer?.parentNode?.removeChild(this.$mapContainer);
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
delete window.initAMap;
|
|
||||||
const $jsapi = document.getElementById(AMAP_SCRIPT_ID);
|
|
||||||
if ($jsapi) {
|
|
||||||
document.head.removeChild($jsapi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMapContainer() {
|
public getMapContainer() {
|
||||||
|
@ -586,7 +337,7 @@ export default class AMapService
|
||||||
this.cameraChangedCallback = callback;
|
this.cameraChangedCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public initViewPort() {
|
private initViewPort() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const {
|
const {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -699,25 +450,4 @@ export default class AMapService
|
||||||
this.cameraChangedCallback(this.viewport);
|
this.cameraChangedCallback(this.viewport);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private getMapStyle(name: string): string {
|
|
||||||
return MapTheme[name] ? MapTheme[name] : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
let $wrapper = id as HTMLDivElement;
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
$wrapper = document.getElementById(id) as HTMLDivElement;
|
|
||||||
}
|
|
||||||
const $amapdiv = document.createElement('div');
|
|
||||||
$amapdiv.style.cssText += `
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
$amapdiv.id = 'l7_amap_div' + mapdivCount++;
|
|
||||||
$wrapper.appendChild($amapdiv);
|
|
||||||
return $amapdiv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default class Viewport implements IViewport {
|
||||||
|
|
||||||
private cameraPosition: vec3 = vec3.create();
|
private cameraPosition: vec3 = vec3.create();
|
||||||
|
|
||||||
private viewport: WebMercatorViewport;
|
protected viewport: WebMercatorViewport;
|
||||||
|
|
||||||
private projectionMatrix: mat4 = mat4.create();
|
private projectionMatrix: mat4 = mat4.create();
|
||||||
private modelMatrix: mat4 = mat4.create();
|
private modelMatrix: mat4 = mat4.create();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Map } from '@antv/l7-map';
|
import { Map } from '@antv/l7-map';
|
||||||
import BaseMapWrapper from '../BaseMapWrapper';
|
import BaseMapWrapper from '../utils/BaseMapWrapper';
|
||||||
import MapService from './map';
|
import MapService from './map';
|
||||||
export default class EarthWrapper extends BaseMapWrapper<Map> {
|
export default class EarthWrapper extends BaseMapWrapper<Map> {
|
||||||
protected getServiceConstructor() {
|
protected getServiceConstructor() {
|
||||||
|
|
|
@ -2,27 +2,18 @@
|
||||||
* MapboxService
|
* MapboxService
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
Bounds,
|
|
||||||
CoordinateSystem,
|
CoordinateSystem,
|
||||||
ICoordinateSystemService,
|
|
||||||
IEarthService,
|
IEarthService,
|
||||||
IGlobalConfigService,
|
|
||||||
ILngLat,
|
|
||||||
IMapConfig,
|
|
||||||
IMercator,
|
IMercator,
|
||||||
IPoint,
|
|
||||||
IStatusOptions,
|
|
||||||
IViewport,
|
IViewport,
|
||||||
MapServiceEvent,
|
MapServiceEvent,
|
||||||
MapStyle,
|
|
||||||
TYPES,
|
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { EarthMap, Map } from '@antv/l7-map';
|
import { EarthMap, Map } from '@antv/l7-map';
|
||||||
import { DOM } from '@antv/l7-utils';
|
import { injectable } from 'inversify';
|
||||||
import { inject, injectable } from 'inversify';
|
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { Version } from '../version';
|
import { Version } from '../version';
|
||||||
import Viewport from './Viewport';
|
import Viewport from './Viewport';
|
||||||
|
import BaseMapService from '../utils/BaseMapService';
|
||||||
const EventMap: {
|
const EventMap: {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
} = {
|
} = {
|
||||||
|
@ -31,56 +22,38 @@ const EventMap: {
|
||||||
zoomchange: 'zoom',
|
zoomchange: 'zoom',
|
||||||
dragging: 'drag',
|
dragging: 'drag',
|
||||||
};
|
};
|
||||||
import { ISimpleMapCoord, SimpleMapCoord } from '../simpleMapCoord';
|
|
||||||
import { MapTheme } from './theme';
|
|
||||||
|
|
||||||
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
||||||
/**
|
/**
|
||||||
* EarthService
|
* EarthService
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class L7EarthService implements IEarthService<Map> {
|
export default class L7EarthService extends BaseMapService<Map>
|
||||||
|
implements IEarthService {
|
||||||
|
public lngLatToMercator(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
): IMercator {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
public getModelMatrix(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
rotate: [number, number, number],
|
||||||
|
scale: [number, number, number],
|
||||||
|
origin: IMercator,
|
||||||
|
): number[] {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
public version: string = Version.GLOBEL;
|
public version: string = Version.GLOBEL;
|
||||||
public map: Map;
|
|
||||||
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
|
||||||
|
|
||||||
// TODO: 判断地图是否正在拖拽
|
// TODO: 判断地图是否正在拖拽
|
||||||
public dragging: boolean = false;
|
public dragging: boolean = false;
|
||||||
|
public viewport: Viewport;
|
||||||
|
protected cameraChangedCallback: (viewport: IViewport) => void;
|
||||||
|
|
||||||
// 背景色
|
|
||||||
public bgColor: string = '#000';
|
|
||||||
|
|
||||||
@inject(TYPES.MapConfig)
|
|
||||||
private readonly config: Partial<IMapConfig>;
|
|
||||||
|
|
||||||
@inject(TYPES.IGlobalConfigService)
|
|
||||||
private readonly configService: IGlobalConfigService;
|
|
||||||
|
|
||||||
@inject(TYPES.ICoordinateSystemService)
|
|
||||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
|
||||||
|
|
||||||
@inject(TYPES.IEventEmitter)
|
|
||||||
private eventEmitter: any;
|
|
||||||
private viewport: Viewport;
|
|
||||||
private markerContainer: HTMLElement;
|
|
||||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
|
||||||
private $mapContainer: HTMLElement | null;
|
|
||||||
// T: 用于记录鼠标对相机的控制
|
// T: 用于记录鼠标对相机的控制
|
||||||
private handleCameraChanging: boolean;
|
private handleCameraChanging: boolean;
|
||||||
private handleCameraTimer: any;
|
private handleCameraTimer: any;
|
||||||
public setBgColor(color: string) {
|
|
||||||
this.bgColor = color;
|
|
||||||
}
|
|
||||||
// init
|
|
||||||
public addMarkerContainer(): void {
|
|
||||||
const container = this.map.getCanvasContainer();
|
|
||||||
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
|
||||||
this.markerContainer.setAttribute('tabindex', '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMarkerContainer(): HTMLElement {
|
|
||||||
return this.markerContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map event
|
// map event
|
||||||
public on(type: string, handle: (...args: any[]) => void): void {
|
public on(type: string, handle: (...args: any[]) => void): void {
|
||||||
|
@ -96,10 +69,6 @@ export default class L7EarthService implements IEarthService<Map> {
|
||||||
this.eventEmitter.off(type, handle);
|
this.eventEmitter.off(type, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContainer(): HTMLElement | null {
|
|
||||||
return this.map.getContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapCanvasContainer(): HTMLElement {
|
public getMapCanvasContainer(): HTMLElement {
|
||||||
return this.map.getCanvasContainer() as HTMLElement;
|
return this.map.getCanvasContainer() as HTMLElement;
|
||||||
}
|
}
|
||||||
|
@ -111,170 +80,15 @@ export default class L7EarthService implements IEarthService<Map> {
|
||||||
// get mapStatus method
|
// get mapStatus method
|
||||||
|
|
||||||
public getType() {
|
public getType() {
|
||||||
return 'default';
|
return 'earth';
|
||||||
}
|
|
||||||
|
|
||||||
public getZoom(): number {
|
|
||||||
return this.map.getZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoom(zoom: number) {
|
|
||||||
return this.map.setZoom(zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCenter(): ILngLat {
|
|
||||||
return this.map.getCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setCenter(lnglat: [number, number]): void {
|
|
||||||
this.map.setCenter(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPitch(): number {
|
|
||||||
return this.map.getPitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRotation(): number {
|
|
||||||
return this.map.getBearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBounds(): Bounds {
|
|
||||||
return this.map.getBounds().toArray() as Bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMinZoom(): number {
|
|
||||||
return this.map.getMinZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMaxZoom(): number {
|
|
||||||
return this.map.getMaxZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setRotation(rotation: number): void {
|
|
||||||
this.map.setBearing(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public zoomIn(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomIn(option, eventData);
|
|
||||||
}
|
|
||||||
public zoomOut(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomOut(option, eventData);
|
|
||||||
}
|
|
||||||
public setPitch(pitch: number) {
|
|
||||||
return this.map.setPitch(pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panTo(p: [number, number]): void {
|
|
||||||
this.map.panTo(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panBy(x: number = 0, y: number = 0): void {
|
|
||||||
this.panTo([x, y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public fitBounds(bound: Bounds, fitBoundsOptions?: any): void {
|
|
||||||
this.map.fitBounds(bound, fitBoundsOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMaxZoom(max: number): void {
|
|
||||||
this.map.setMaxZoom(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMinZoom(min: number): void {
|
|
||||||
this.map.setMinZoom(min);
|
|
||||||
}
|
|
||||||
public setMapStatus(option: Partial<IStatusOptions>): void {
|
|
||||||
if (option.doubleClickZoom === true) {
|
|
||||||
this.map.doubleClickZoom.enable();
|
|
||||||
}
|
|
||||||
if (option.doubleClickZoom === false) {
|
|
||||||
this.map.doubleClickZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === false) {
|
|
||||||
this.map.dragPan.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === true) {
|
|
||||||
this.map.dragPan.enable();
|
|
||||||
}
|
|
||||||
if (option.rotateEnable === false) {
|
|
||||||
this.map.dragRotate.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === true) {
|
|
||||||
this.map.dragRotate.enable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === false) {
|
|
||||||
this.map.keyboard.disable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === true) {
|
|
||||||
this.map.keyboard.enable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === false) {
|
|
||||||
this.map.scrollZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === true) {
|
|
||||||
this.map.scrollZoom.enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
|
||||||
this.map.flyTo({
|
|
||||||
zoom,
|
|
||||||
center,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStyle(style: any): void {
|
|
||||||
this.map.setStyle(this.getMapStyle(style));
|
|
||||||
}
|
|
||||||
// TODO: 计算像素坐标
|
|
||||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public meterToCoord(center: [number, number], outer: [number, number]) {
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
public lngLatToMercator(
|
|
||||||
lnglat: [number, number],
|
|
||||||
altitude: number,
|
|
||||||
): IMercator {
|
|
||||||
throw new Error('not implement');
|
|
||||||
}
|
|
||||||
public getModelMatrix(
|
|
||||||
lnglat: [number, number],
|
|
||||||
altitude: number,
|
|
||||||
rotate: [number, number, number],
|
|
||||||
scale: [number, number, number] = [1, 1, 1],
|
|
||||||
origin: IMercator = { x: 0, y: 0, z: 0 },
|
|
||||||
): number[] {
|
|
||||||
throw new Error('not implement');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
const {
|
const { id = 'map', style = 'light', rotation = 0, ...rest } = this.config;
|
||||||
id = 'map',
|
|
||||||
attributionControl = false,
|
|
||||||
style = 'light',
|
|
||||||
rotation = 0,
|
|
||||||
mapInstance,
|
|
||||||
...rest
|
|
||||||
} = this.config;
|
|
||||||
|
|
||||||
this.viewport = new Viewport();
|
this.viewport = new Viewport();
|
||||||
|
|
||||||
this.$mapContainer = this.creatAmapContainer(id);
|
this.$mapContainer = this.creatMapContainer(id);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.map = new EarthMap({
|
this.map = new EarthMap({
|
||||||
container: this.$mapContainer,
|
container: this.$mapContainer,
|
||||||
|
@ -311,14 +125,6 @@ export default class L7EarthService implements IEarthService<Map> {
|
||||||
return this.$mapContainer;
|
return this.$mapContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public exportMap(type: 'jpg' | 'png'): string {
|
|
||||||
const renderCanvas = this.map.getCanvas();
|
|
||||||
const layersPng =
|
|
||||||
type === 'jpg'
|
|
||||||
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
|
||||||
: (renderCanvas?.toDataURL('image/png') as string);
|
|
||||||
return layersPng;
|
|
||||||
}
|
|
||||||
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||||
this.cameraChangedCallback = callback;
|
this.cameraChangedCallback = callback;
|
||||||
}
|
}
|
||||||
|
@ -346,7 +152,7 @@ export default class L7EarthService implements IEarthService<Map> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleCameraChanged = (e: any) => {
|
protected handleCameraChanged = (e: any) => {
|
||||||
// Tip: 统一触发地图变化事件
|
// Tip: 统一触发地图变化事件
|
||||||
this.emit('mapchange');
|
this.emit('mapchange');
|
||||||
const DELAY_TIME = 2000;
|
const DELAY_TIME = 2000;
|
||||||
|
@ -405,18 +211,4 @@ export default class L7EarthService implements IEarthService<Map> {
|
||||||
|
|
||||||
this.cameraChangedCallback(this.viewport);
|
this.cameraChangedCallback(this.viewport);
|
||||||
};
|
};
|
||||||
|
|
||||||
private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
let $wrapper = id as HTMLDivElement;
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
$wrapper = document.getElementById(id) as HTMLDivElement;
|
|
||||||
}
|
|
||||||
return $wrapper;
|
|
||||||
}
|
|
||||||
private getMapStyle(name: MapStyle) {
|
|
||||||
if (typeof name !== 'string') {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return MapTheme[name] ? MapTheme[name] : name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,3 +10,5 @@ import { Version } from './version';
|
||||||
export { Version, GaodeMap, GaodeMapV2, Mapbox, Map, Earth };
|
export { Version, GaodeMap, GaodeMapV2, Mapbox, Map, Earth };
|
||||||
// export { GaodeMap, GaodeMapV2, Mapbox, Map };
|
// export { GaodeMap, GaodeMapV2, Mapbox, Map };
|
||||||
// export { Map };
|
// export { Map };
|
||||||
|
|
||||||
|
export * from './utils'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Map } from '@antv/l7-map';
|
import { Map } from '@antv/l7-map';
|
||||||
import BaseMapWrapper from '../BaseMapWrapper';
|
import BaseMapWrapper from '../utils/BaseMapWrapper';
|
||||||
import MapService from './map';
|
import MapService from './map';
|
||||||
export default class MapboxWrapper extends BaseMapWrapper<Map> {
|
export default class MapboxWrapper extends BaseMapWrapper<Map> {
|
||||||
protected getServiceConstructor() {
|
protected getServiceConstructor() {
|
||||||
|
|
|
@ -1,275 +1,41 @@
|
||||||
/**
|
/**
|
||||||
* MapboxService
|
* MapboxService
|
||||||
*/
|
*/
|
||||||
import {
|
import { CoordinateSystem, IMercator } from '@antv/l7-core';
|
||||||
Bounds,
|
|
||||||
CoordinateSystem,
|
|
||||||
ICoordinateSystemService,
|
|
||||||
IGlobalConfigService,
|
|
||||||
ILngLat,
|
|
||||||
IMapConfig,
|
|
||||||
IMapService,
|
|
||||||
IMercator,
|
|
||||||
IPoint,
|
|
||||||
IStatusOptions,
|
|
||||||
IViewport,
|
|
||||||
MapServiceEvent,
|
|
||||||
MapStyle,
|
|
||||||
TYPES,
|
|
||||||
} from '@antv/l7-core';
|
|
||||||
import { Map } from '@antv/l7-map';
|
import { Map } from '@antv/l7-map';
|
||||||
import { $window, DOM } from '@antv/l7-utils';
|
import { $window } from '@antv/l7-utils';
|
||||||
import { inject, injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { ISimpleMapCoord, SimpleMapCoord } from '../simpleMapCoord';
|
|
||||||
import { Version } from '../version';
|
import { Version } from '../version';
|
||||||
import Viewport from './Viewport';
|
import Viewport from '../utils/Viewport';
|
||||||
const EventMap: {
|
import BaseMapService from '../utils/BaseMapService';
|
||||||
[key: string]: any;
|
|
||||||
} = {
|
|
||||||
mapmove: 'move',
|
|
||||||
camerachange: 'move',
|
|
||||||
zoomchange: 'zoom',
|
|
||||||
dragging: 'drag',
|
|
||||||
};
|
|
||||||
import { MapTheme } from './theme';
|
|
||||||
|
|
||||||
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
||||||
/**
|
/**
|
||||||
* AMapService
|
* AMapService
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class L7MapService implements IMapService<Map> {
|
export default class L7MapService extends BaseMapService<Map> {
|
||||||
public version: string = Version.L7MAP;
|
|
||||||
public map: Map;
|
|
||||||
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
|
||||||
// 背景色
|
|
||||||
public bgColor: string = 'rgba(0.0, 0.0, 0.0, 0.0)';
|
|
||||||
|
|
||||||
@inject(TYPES.MapConfig)
|
|
||||||
private readonly config: Partial<IMapConfig>;
|
|
||||||
|
|
||||||
@inject(TYPES.IGlobalConfigService)
|
|
||||||
private readonly configService: IGlobalConfigService;
|
|
||||||
|
|
||||||
@inject(TYPES.ICoordinateSystemService)
|
|
||||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
|
||||||
|
|
||||||
@inject(TYPES.IEventEmitter)
|
|
||||||
private eventEmitter: any;
|
|
||||||
private viewport: Viewport;
|
|
||||||
private markerContainer: HTMLElement;
|
|
||||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
|
||||||
private $mapContainer: HTMLElement | null;
|
|
||||||
public setBgColor(color: string) {
|
|
||||||
this.bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init
|
|
||||||
public addMarkerContainer(): void {
|
|
||||||
const container = this.map.getCanvasContainer();
|
|
||||||
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
|
||||||
this.markerContainer.setAttribute('tabindex', '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMarkerContainer(): HTMLElement {
|
|
||||||
return this.markerContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map event
|
|
||||||
public on(type: string, handle: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.on(type, handle);
|
|
||||||
} else {
|
|
||||||
// 统一事件名称
|
|
||||||
this.map.on(EventMap[type] || type, handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public off(type: string, handle: (...args: any[]) => void): void {
|
|
||||||
this.map.off(EventMap[type] || type, handle);
|
|
||||||
this.eventEmitter.off(type, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getContainer(): HTMLElement | null {
|
|
||||||
return this.map.getContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapCanvasContainer(): HTMLElement {
|
|
||||||
return this.map.getCanvasContainer() as HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSize(): [number, number] {
|
|
||||||
if (this.version === Version.SIMPLE) {
|
|
||||||
return this.simpleMapCoord.getSize();
|
|
||||||
}
|
|
||||||
const size = this.map.transform;
|
|
||||||
|
|
||||||
return [size.width, size.height];
|
|
||||||
}
|
|
||||||
// get mapStatus method
|
|
||||||
|
|
||||||
public getType() {
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
public getZoom(): number {
|
|
||||||
return this.map.getZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoom(zoom: number) {
|
|
||||||
return this.map.setZoom(zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCenter(): ILngLat {
|
|
||||||
return this.map.getCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setCenter(lnglat: [number, number]): void {
|
|
||||||
this.map.setCenter(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPitch(): number {
|
|
||||||
return this.map.getPitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRotation(): number {
|
|
||||||
return this.map.getBearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBounds(): Bounds {
|
|
||||||
return this.map.getBounds().toArray() as Bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMinZoom(): number {
|
|
||||||
return this.map.getMinZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMaxZoom(): number {
|
|
||||||
return this.map.getMaxZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setRotation(rotation: number): void {
|
|
||||||
this.map.setBearing(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public zoomIn(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomIn(option, eventData);
|
|
||||||
}
|
|
||||||
public zoomOut(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomOut(option, eventData);
|
|
||||||
}
|
|
||||||
public setPitch(pitch: number) {
|
|
||||||
return this.map.setPitch(pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panTo(p: [number, number]): void {
|
|
||||||
this.map.panTo(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panBy(x: number = 0, y: number = 0): void {
|
|
||||||
this.panTo([x, y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public fitBounds(bound: Bounds, fitBoundsOptions?: any): void {
|
|
||||||
this.map.fitBounds(bound, fitBoundsOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMaxZoom(max: number): void {
|
|
||||||
this.map.setMaxZoom(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMinZoom(min: number): void {
|
|
||||||
this.map.setMinZoom(min);
|
|
||||||
}
|
|
||||||
public setMapStatus(option: Partial<IStatusOptions>): void {
|
|
||||||
if (option.doubleClickZoom === true) {
|
|
||||||
this.map.doubleClickZoom.enable();
|
|
||||||
}
|
|
||||||
if (option.doubleClickZoom === false) {
|
|
||||||
this.map.doubleClickZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === false) {
|
|
||||||
this.map.dragPan.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === true) {
|
|
||||||
this.map.dragPan.enable();
|
|
||||||
}
|
|
||||||
if (option.rotateEnable === false) {
|
|
||||||
this.map.dragRotate.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === true) {
|
|
||||||
this.map.dragRotate.enable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === false) {
|
|
||||||
this.map.keyboard.disable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === true) {
|
|
||||||
this.map.keyboard.enable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === false) {
|
|
||||||
this.map.scrollZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === true) {
|
|
||||||
this.map.scrollZoom.enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
|
||||||
this.map.flyTo({
|
|
||||||
zoom,
|
|
||||||
center,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStyle(style: any): void {
|
|
||||||
this.map.setStyle(this.getMapStyle(style));
|
|
||||||
}
|
|
||||||
|
|
||||||
public meterToCoord(center: [number, number], outer: [number, number]) {
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 计算像素坐标
|
|
||||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
public lngLatToMercator(
|
public lngLatToMercator(
|
||||||
lnglat: [number, number],
|
_lnglat: [number, number],
|
||||||
altitude: number,
|
_altitude: number,
|
||||||
): IMercator {
|
): IMercator {
|
||||||
throw new Error('not implement');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
public getModelMatrix(
|
public getModelMatrix(): number[] {
|
||||||
lnglat: [number, number],
|
throw new Error('Method not implemented.');
|
||||||
altitude: number,
|
|
||||||
rotate: [number, number, number],
|
|
||||||
scale: [number, number, number] = [1, 1, 1],
|
|
||||||
origin: IMercator = { x: 0, y: 0, z: 0 },
|
|
||||||
): number[] {
|
|
||||||
throw new Error('not implement');
|
|
||||||
}
|
}
|
||||||
|
public viewport: Viewport;
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
public async init(): Promise<void> {
|
||||||
const {
|
const {
|
||||||
id = 'map',
|
id = 'map',
|
||||||
attributionControl = false,
|
|
||||||
style = 'light',
|
style = 'light',
|
||||||
rotation = 0,
|
rotation = 0,
|
||||||
mapInstance,
|
mapInstance,
|
||||||
version = 'L7MAP',
|
version = 'L7MAP',
|
||||||
mapSize = 10000,
|
mapSize = 10000,
|
||||||
|
interactive = true,
|
||||||
...rest
|
...rest
|
||||||
} = this.config;
|
} = this.config;
|
||||||
|
|
||||||
|
@ -277,26 +43,17 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.simpleMapCoord.setSize(mapSize);
|
this.simpleMapCoord.setSize(mapSize);
|
||||||
// console.log('this.config.center', this.config.center)
|
|
||||||
if (version === Version.SIMPLE && rest.center) {
|
if (version === Version.SIMPLE && rest.center) {
|
||||||
rest.center = this.simpleMapCoord.unproject(
|
rest.center = this.simpleMapCoord.unproject(
|
||||||
rest.center as [number, number],
|
rest.center as [number, number],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// console.log(this.simpleMapCoord.project(this.config.center as [number, number]))
|
|
||||||
// console.log(this.simpleMapCoord.unproject([500, 500]))
|
|
||||||
// console.log(this.simpleMapCoord.project([0, 0]))
|
|
||||||
// console.log(this.simpleMapCoord.unproject([5000, 5000]))
|
|
||||||
|
|
||||||
// console.log(this.simpleMapCoord.unproject([200, 200]))
|
|
||||||
// console.log(this.simpleMapCoord.unproject([1000, 1000]))
|
|
||||||
|
|
||||||
if (mapInstance) {
|
if (mapInstance) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.map = mapInstance;
|
this.map = mapInstance;
|
||||||
this.$mapContainer = this.map.getContainer();
|
this.$mapContainer = this.map.getContainer();
|
||||||
} else {
|
} else {
|
||||||
this.$mapContainer = this.creatAmapContainer(id);
|
this.$mapContainer = this.creatMapContainer(id);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.map = new Map({
|
this.map = new Map({
|
||||||
container: this.$mapContainer,
|
container: this.$mapContainer,
|
||||||
|
@ -307,7 +64,10 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.map.on('load', this.handleCameraChanged);
|
this.map.on('load', this.handleCameraChanged);
|
||||||
|
if (interactive) {
|
||||||
|
// L7 作为第三方地图插件时关闭重绘
|
||||||
this.map.on('move', this.handleCameraChanged);
|
this.map.on('move', this.handleCameraChanged);
|
||||||
|
}
|
||||||
|
|
||||||
// 不同于高德地图,需要手动触发首次渲染
|
// 不同于高德地图,需要手动触发首次渲染
|
||||||
this.handleCameraChanged();
|
this.handleCameraChanged();
|
||||||
|
@ -317,7 +77,6 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
public async initMiniMap(): Promise<void> {
|
public async initMiniMap(): Promise<void> {
|
||||||
const {
|
const {
|
||||||
id = 'map',
|
id = 'map',
|
||||||
attributionControl = false,
|
|
||||||
style = 'light',
|
style = 'light',
|
||||||
rotation = 0,
|
rotation = 0,
|
||||||
mapInstance,
|
mapInstance,
|
||||||
|
@ -372,24 +131,6 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
|
||||||
this.eventEmitter.removeAllListeners();
|
|
||||||
if (this.map) {
|
|
||||||
this.map.remove();
|
|
||||||
this.$mapContainer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public emit(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.emit(name, ...args);
|
|
||||||
}
|
|
||||||
public once(name: string, ...args: any[]) {
|
|
||||||
this.eventEmitter.once(name, ...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapContainer() {
|
|
||||||
return this.$mapContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public exportMap(type: 'jpg' | 'png'): string {
|
public exportMap(type: 'jpg' | 'png'): string {
|
||||||
const renderCanvas = this.map.getCanvas();
|
const renderCanvas = this.map.getCanvas();
|
||||||
const layersPng =
|
const layersPng =
|
||||||
|
@ -398,9 +139,6 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
: (renderCanvas?.toDataURL('image/png') as string);
|
: (renderCanvas?.toDataURL('image/png') as string);
|
||||||
return layersPng;
|
return layersPng;
|
||||||
}
|
}
|
||||||
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
|
||||||
this.cameraChangedCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 处理小程序中有底图模式下的相机跟新
|
// TODO: 处理小程序中有底图模式下的相机跟新
|
||||||
private handleMiniCameraChanged = (
|
private handleMiniCameraChanged = (
|
||||||
|
@ -439,49 +177,4 @@ export default class L7MapService implements IMapService<Map> {
|
||||||
|
|
||||||
this.cameraChangedCallback(this.viewport);
|
this.cameraChangedCallback(this.viewport);
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleCameraChanged = () => {
|
|
||||||
const { lat, lng } = this.map.getCenter();
|
|
||||||
const { offsetCoordinate = true } = this.config;
|
|
||||||
// Tip: 统一触发地图变化事件
|
|
||||||
this.emit('mapchange');
|
|
||||||
// resync
|
|
||||||
this.viewport.syncWithMapCamera({
|
|
||||||
bearing: this.map.getBearing(),
|
|
||||||
center: [lng, lat],
|
|
||||||
viewportHeight: this.map.transform.height,
|
|
||||||
pitch: this.map.getPitch(),
|
|
||||||
viewportWidth: this.map.transform.width,
|
|
||||||
zoom: this.map.getZoom(),
|
|
||||||
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
|
||||||
cameraHeight: 0,
|
|
||||||
});
|
|
||||||
// set coordinate system
|
|
||||||
if (
|
|
||||||
this.viewport.getZoom() > LNGLAT_OFFSET_ZOOM_THRESHOLD &&
|
|
||||||
offsetCoordinate
|
|
||||||
) {
|
|
||||||
this.coordinateSystemService.setCoordinateSystem(
|
|
||||||
CoordinateSystem.LNGLAT_OFFSET,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.LNGLAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cameraChangedCallback(this.viewport);
|
|
||||||
};
|
|
||||||
|
|
||||||
private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
let $wrapper = id as HTMLDivElement;
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
$wrapper = document.getElementById(id) as HTMLDivElement;
|
|
||||||
}
|
|
||||||
return $wrapper;
|
|
||||||
}
|
|
||||||
private getMapStyle(name: MapStyle) {
|
|
||||||
if (typeof name !== 'string') {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return MapTheme[name] ? MapTheme[name] : name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { IMapCamera, IViewport } from '@antv/l7-core';
|
||||||
import WebMercatorViewport from 'viewport-mercator-project';
|
import WebMercatorViewport from 'viewport-mercator-project';
|
||||||
|
|
||||||
export default class Viewport implements IViewport {
|
export default class Viewport implements IViewport {
|
||||||
private viewport: WebMercatorViewport;
|
public viewport: WebMercatorViewport;
|
||||||
|
|
||||||
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Map } from 'mapbox-gl';
|
import { Map } from 'mapbox-gl';
|
||||||
import { IMapboxInstance } from '../../typings/index';
|
import { IMapboxInstance } from '../../typings/index';
|
||||||
import BaseMapWrapper from '../BaseMapWrapper';
|
import BaseMapWrapper from '../utils/BaseMapWrapper';
|
||||||
import './logo.css';
|
import './logo.css';
|
||||||
import MapboxService from './map';
|
import MapboxService from './map';
|
||||||
export default class MapboxWrapper extends BaseMapWrapper<
|
export default class MapboxWrapper extends BaseMapWrapper<
|
||||||
|
|
|
@ -1,252 +1,36 @@
|
||||||
/**
|
/**
|
||||||
* MapboxService
|
* MapboxService
|
||||||
*/
|
*/
|
||||||
import {
|
import { IMercator } from '@antv/l7-core';
|
||||||
Bounds,
|
|
||||||
CoordinateSystem,
|
|
||||||
ICoordinateSystemService,
|
|
||||||
IGlobalConfigService,
|
|
||||||
ILngLat,
|
|
||||||
IMapConfig,
|
|
||||||
IMapService,
|
|
||||||
IMercator,
|
|
||||||
IPoint,
|
|
||||||
IStatusOptions,
|
|
||||||
IViewport,
|
|
||||||
MapServiceEvent,
|
|
||||||
MapStyle,
|
|
||||||
TYPES,
|
|
||||||
} from '@antv/l7-core';
|
|
||||||
import { DOM } from '@antv/l7-utils';
|
|
||||||
import { mat4, vec3 } from 'gl-matrix';
|
import { mat4, vec3 } from 'gl-matrix';
|
||||||
import { inject, injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import mapboxgl, { Map } from 'mapbox-gl';
|
import mapboxgl, { Map } from 'mapbox-gl';
|
||||||
// tslint:disable-next-line:no-submodule-imports
|
// tslint:disable-next-line:no-submodule-imports
|
||||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { IMapboxInstance } from '../../typings/index';
|
import { IMapboxInstance } from '../../typings/index';
|
||||||
import { Version } from '../version';
|
|
||||||
import Viewport from './Viewport';
|
import Viewport from './Viewport';
|
||||||
|
import BaseMapService from '../utils/BaseMapService';
|
||||||
window.mapboxgl = mapboxgl;
|
window.mapboxgl = mapboxgl;
|
||||||
const EventMap: {
|
|
||||||
[key: string]: any;
|
|
||||||
} = {
|
|
||||||
mapmove: 'move',
|
|
||||||
camerachange: 'move',
|
|
||||||
zoomchange: 'zoom',
|
|
||||||
dragging: 'drag',
|
|
||||||
};
|
|
||||||
import { ISimpleMapCoord, SimpleMapCoord } from '../simpleMapCoord';
|
|
||||||
import { MapTheme } from './theme';
|
|
||||||
let mapdivCount = 0;
|
let mapdivCount = 0;
|
||||||
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
|
||||||
const MAPBOX_API_KEY =
|
const MAPBOX_API_KEY =
|
||||||
// 'pk.eyJ1IjoibHp4dWUiLCJhIjoiY2tvaWZuM2s4MWZuYjJ1dHI5ZGduYTlrdiJ9.DQCfMRbZzx0VSwecQ69McA';
|
|
||||||
'pk.eyJ1IjoiMTg5Njk5NDg2MTkiLCJhIjoiY2s5OXVzdHlzMDVneDNscDVjdzVmeXl0dyJ9.81SQ5qaJS0xExYLbDZAGpQ';
|
'pk.eyJ1IjoiMTg5Njk5NDg2MTkiLCJhIjoiY2s5OXVzdHlzMDVneDNscDVjdzVmeXl0dyJ9.81SQ5qaJS0xExYLbDZAGpQ';
|
||||||
/**
|
/**
|
||||||
* AMapService
|
* AMapService
|
||||||
*/
|
*/
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class MapboxService
|
export default class MapboxService extends BaseMapService<
|
||||||
implements IMapService<Map & IMapboxInstance> {
|
Map & IMapboxInstance
|
||||||
public version: string = Version.MAPBOX;
|
> {
|
||||||
public map: Map & IMapboxInstance;
|
|
||||||
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
|
||||||
|
|
||||||
// 背景色
|
|
||||||
public bgColor: string = 'rgba(0.0, 0.0, 0.0, 0.0)';
|
|
||||||
|
|
||||||
@inject(TYPES.MapConfig)
|
|
||||||
private readonly config: Partial<IMapConfig>;
|
|
||||||
|
|
||||||
@inject(TYPES.IGlobalConfigService)
|
|
||||||
private readonly configService: IGlobalConfigService;
|
|
||||||
|
|
||||||
@inject(TYPES.ICoordinateSystemService)
|
|
||||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
|
||||||
|
|
||||||
@inject(TYPES.IEventEmitter)
|
|
||||||
private eventEmitter: any;
|
|
||||||
private viewport: Viewport;
|
|
||||||
private markerContainer: HTMLElement;
|
|
||||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
|
||||||
private $mapContainer: HTMLElement | null;
|
|
||||||
public setBgColor(color: string) {
|
|
||||||
this.bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init
|
|
||||||
public addMarkerContainer(): void {
|
|
||||||
const container = this.map.getCanvasContainer();
|
|
||||||
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
|
||||||
this.markerContainer.setAttribute('tabindex', '-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMarkerContainer(): HTMLElement {
|
|
||||||
return this.markerContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map event
|
|
||||||
public on(type: string, handle: (...args: any[]) => void): void {
|
|
||||||
if (MapServiceEvent.indexOf(type) !== -1) {
|
|
||||||
this.eventEmitter.on(type, handle);
|
|
||||||
} else {
|
|
||||||
// 统一事件名称
|
|
||||||
this.map.on(EventMap[type] || type, handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public off(type: string, handle: (...args: any[]) => void): void {
|
|
||||||
this.map.off(EventMap[type] || type, handle);
|
|
||||||
this.eventEmitter.off(type, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getContainer(): HTMLElement | null {
|
|
||||||
return this.map.getContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMapCanvasContainer(): HTMLElement {
|
|
||||||
return this.map.getCanvasContainer() as HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSize(): [number, number] {
|
|
||||||
const size = this.map.transform;
|
|
||||||
return [size.width, size.height];
|
|
||||||
}
|
|
||||||
// get mapStatus method
|
// get mapStatus method
|
||||||
|
|
||||||
|
public viewport: Viewport;
|
||||||
|
|
||||||
public getType() {
|
public getType() {
|
||||||
return 'mapbox';
|
return 'mapbox';
|
||||||
}
|
}
|
||||||
|
|
||||||
public getZoom(): number {
|
|
||||||
return this.map.getZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoom(zoom: number) {
|
|
||||||
return this.map.setZoom(zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCenter(): ILngLat {
|
|
||||||
return this.map.getCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setCenter(lnglat: [number, number]): void {
|
|
||||||
this.map.setCenter(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPitch(): number {
|
|
||||||
return this.map.getPitch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRotation(): number {
|
|
||||||
return this.map.getBearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBounds(): Bounds {
|
|
||||||
return this.map.getBounds().toArray() as Bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMinZoom(): number {
|
|
||||||
return this.map.getMinZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getMaxZoom(): number {
|
|
||||||
return this.map.getMaxZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setRotation(rotation: number): void {
|
|
||||||
this.map.setBearing(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public zoomIn(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomIn(option, eventData);
|
|
||||||
}
|
|
||||||
public zoomOut(option?: any, eventData?: any): void {
|
|
||||||
this.map.zoomOut(option, eventData);
|
|
||||||
}
|
|
||||||
public setPitch(pitch: number) {
|
|
||||||
return this.map.setPitch(pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panTo(p: [number, number]): void {
|
|
||||||
this.map.panTo(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public panBy(x: number, y: number): void {
|
|
||||||
this.panTo([x, y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void {
|
|
||||||
this.map.fitBounds(bound, fitBoundsOptions as mapboxgl.FitBoundsOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMaxZoom(max: number): void {
|
|
||||||
this.map.setMaxZoom(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMinZoom(min: number): void {
|
|
||||||
this.map.setMinZoom(min);
|
|
||||||
}
|
|
||||||
public setMapStatus(option: Partial<IStatusOptions>): void {
|
|
||||||
if (option.doubleClickZoom === true) {
|
|
||||||
this.map.doubleClickZoom.enable();
|
|
||||||
}
|
|
||||||
if (option.doubleClickZoom === false) {
|
|
||||||
this.map.doubleClickZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === false) {
|
|
||||||
this.map.dragPan.disable();
|
|
||||||
}
|
|
||||||
if (option.dragEnable === true) {
|
|
||||||
this.map.dragPan.enable();
|
|
||||||
}
|
|
||||||
if (option.rotateEnable === false) {
|
|
||||||
this.map.dragRotate.disable();
|
|
||||||
}
|
|
||||||
if (option.rotateEnable === true) {
|
|
||||||
this.map.dragRotate.enable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === false) {
|
|
||||||
this.map.keyboard.disable();
|
|
||||||
}
|
|
||||||
if (option.keyboardEnable === true) {
|
|
||||||
this.map.keyboard.enable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === false) {
|
|
||||||
this.map.scrollZoom.disable();
|
|
||||||
}
|
|
||||||
if (option.zoomEnable === true) {
|
|
||||||
this.map.scrollZoom.enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
|
||||||
this.map.flyTo({
|
|
||||||
zoom,
|
|
||||||
center,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public setMapStyle(style: any): void {
|
|
||||||
this.map.setStyle(this.getMapStyle(style));
|
|
||||||
}
|
|
||||||
// TODO: 计算像素坐标
|
|
||||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
|
||||||
return this.map.unproject(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
|
||||||
return this.map.project(lnglat);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将经纬度转成墨卡托坐标
|
* 将经纬度转成墨卡托坐标
|
||||||
* @param lnglat
|
* @param lnglat
|
||||||
|
@ -354,7 +138,7 @@ export default class MapboxService
|
||||||
this.map = mapInstance;
|
this.map = mapInstance;
|
||||||
this.$mapContainer = this.map.getContainer();
|
this.$mapContainer = this.map.getContainer();
|
||||||
} else {
|
} else {
|
||||||
this.$mapContainer = this.creatAmapContainer(id);
|
this.$mapContainer = this.creatMapContainer(id);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.map = new window.mapboxgl.Map({
|
this.map = new window.mapboxgl.Map({
|
||||||
container: this.$mapContainer,
|
container: this.$mapContainer,
|
||||||
|
@ -427,49 +211,8 @@ export default class MapboxService
|
||||||
: (renderCanvas?.toDataURL('image/png') as string);
|
: (renderCanvas?.toDataURL('image/png') as string);
|
||||||
return layersPng;
|
return layersPng;
|
||||||
}
|
}
|
||||||
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
|
||||||
this.cameraChangedCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleCameraChanged = () => {
|
protected creatMapContainer(id: string | HTMLDivElement) {
|
||||||
// @see https://github.com/mapbox/mapbox-gl-js/issues/2572
|
|
||||||
const { lat, lng } = this.map.getCenter().wrap();
|
|
||||||
// Tip: 统一触发地图变化事件
|
|
||||||
this.emit('mapchange');
|
|
||||||
// resync
|
|
||||||
this.viewport.syncWithMapCamera({
|
|
||||||
bearing: this.map.getBearing(),
|
|
||||||
center: [lng, lat],
|
|
||||||
viewportHeight: this.map.transform.height,
|
|
||||||
pitch: this.map.getPitch(),
|
|
||||||
viewportWidth: this.map.transform.width,
|
|
||||||
zoom: this.map.getZoom(),
|
|
||||||
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
|
||||||
cameraHeight: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { offsetZoom = LNGLAT_OFFSET_ZOOM_THRESHOLD } = this.config;
|
|
||||||
|
|
||||||
// set coordinate system
|
|
||||||
if (this.viewport.getZoom() > offsetZoom) {
|
|
||||||
this.coordinateSystemService.setCoordinateSystem(
|
|
||||||
CoordinateSystem.LNGLAT_OFFSET,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.LNGLAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cameraChangedCallback(this.viewport);
|
|
||||||
};
|
|
||||||
|
|
||||||
// private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
// let $wrapper = id as HTMLDivElement;
|
|
||||||
// if (typeof id === 'string') {
|
|
||||||
// $wrapper = document.getElementById(id) as HTMLDivElement;
|
|
||||||
// }
|
|
||||||
// return $wrapper;
|
|
||||||
// }
|
|
||||||
private creatAmapContainer(id: string | HTMLDivElement) {
|
|
||||||
let $wrapper = id as HTMLDivElement;
|
let $wrapper = id as HTMLDivElement;
|
||||||
if (typeof id === 'string') {
|
if (typeof id === 'string') {
|
||||||
$wrapper = document.getElementById(id) as HTMLDivElement;
|
$wrapper = document.getElementById(id) as HTMLDivElement;
|
||||||
|
@ -485,10 +228,4 @@ export default class MapboxService
|
||||||
$wrapper.appendChild($amapdiv);
|
$wrapper.appendChild($amapdiv);
|
||||||
return $amapdiv;
|
return $amapdiv;
|
||||||
}
|
}
|
||||||
private getMapStyle(name: MapStyle) {
|
|
||||||
if (typeof name !== 'string') {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return MapTheme[name] ? MapTheme[name] : name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,363 @@
|
||||||
|
/**
|
||||||
|
* MapboxService
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
Bounds,
|
||||||
|
CoordinateSystem,
|
||||||
|
ICoordinateSystemService,
|
||||||
|
IGlobalConfigService,
|
||||||
|
ILngLat,
|
||||||
|
IMapCamera,
|
||||||
|
IMapConfig,
|
||||||
|
IMapService,
|
||||||
|
IMercator,
|
||||||
|
IPoint,
|
||||||
|
IStatusOptions,
|
||||||
|
IViewport,
|
||||||
|
MapServiceEvent,
|
||||||
|
MapStyle,
|
||||||
|
TYPES,
|
||||||
|
} from '@antv/l7-core';
|
||||||
|
import { Map } from '@antv/l7-map';
|
||||||
|
import { DOM } from '@antv/l7-utils';
|
||||||
|
import { inject, injectable } from 'inversify';
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import { ISimpleMapCoord, SimpleMapCoord } from './simpleMapCoord';
|
||||||
|
import { Version } from '../version';
|
||||||
|
const EventMap: {
|
||||||
|
[key: string]: any;
|
||||||
|
} = {
|
||||||
|
mapmove: 'move',
|
||||||
|
camerachange: 'move',
|
||||||
|
zoomchange: 'zoom',
|
||||||
|
dragging: 'drag',
|
||||||
|
};
|
||||||
|
import { MapTheme } from './theme';
|
||||||
|
|
||||||
|
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
||||||
|
/**
|
||||||
|
* AMapService
|
||||||
|
*/
|
||||||
|
@injectable()
|
||||||
|
export default abstract class BaseMapService<T> implements IMapService<Map & T> {
|
||||||
|
public version: string = Version.L7MAP;
|
||||||
|
public map: Map & T;
|
||||||
|
protected viewport: IViewport | unknown;
|
||||||
|
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
||||||
|
// 背景色
|
||||||
|
public bgColor: string = 'rgba(0.0, 0.0, 0.0, 0.0)';
|
||||||
|
|
||||||
|
@inject(TYPES.MapConfig)
|
||||||
|
protected readonly config: Partial<IMapConfig>;
|
||||||
|
|
||||||
|
@inject(TYPES.IGlobalConfigService)
|
||||||
|
protected readonly configService: IGlobalConfigService;
|
||||||
|
|
||||||
|
@inject(TYPES.ICoordinateSystemService)
|
||||||
|
protected readonly coordinateSystemService: ICoordinateSystemService;
|
||||||
|
|
||||||
|
@inject(TYPES.IEventEmitter)
|
||||||
|
protected eventEmitter: any;
|
||||||
|
|
||||||
|
protected markerContainer: HTMLElement;
|
||||||
|
protected cameraChangedCallback: (viewport: IViewport) => void;
|
||||||
|
protected $mapContainer: HTMLElement | null;
|
||||||
|
public setBgColor(color: string) {
|
||||||
|
this.bgColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init
|
||||||
|
public addMarkerContainer(): void {
|
||||||
|
const container = this.map.getCanvasContainer();
|
||||||
|
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
||||||
|
this.markerContainer.setAttribute('tabindex', '-1');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMarkerContainer(): HTMLElement {
|
||||||
|
return this.markerContainer;
|
||||||
|
}
|
||||||
|
public getOverlayContainer(): HTMLElement | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map event
|
||||||
|
public on(type: string, handle: (...args: any[]) => void): void {
|
||||||
|
if (MapServiceEvent.indexOf(type) !== -1) {
|
||||||
|
this.eventEmitter.on(type, handle);
|
||||||
|
} else {
|
||||||
|
// 统一事件名称
|
||||||
|
this.map.on(EventMap[type] || type, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public off(type: string, handle: (...args: any[]) => void): void {
|
||||||
|
this.map.off(EventMap[type] || type, handle);
|
||||||
|
this.eventEmitter.off(type, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getContainer(): HTMLElement | null {
|
||||||
|
return this.map.getContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapCanvasContainer(): HTMLElement {
|
||||||
|
return this.map.getCanvasContainer() as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSize(): [number, number] {
|
||||||
|
if (this.version === Version.SIMPLE) {
|
||||||
|
return this.simpleMapCoord.getSize();
|
||||||
|
}
|
||||||
|
const size = this.map.transform;
|
||||||
|
|
||||||
|
return [size.width, size.height];
|
||||||
|
}
|
||||||
|
// get mapStatus method
|
||||||
|
|
||||||
|
public getType() {
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
public getZoom(): number {
|
||||||
|
return this.map.getZoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setZoom(zoom: number) {
|
||||||
|
return this.map.setZoom(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCenter(): ILngLat {
|
||||||
|
return this.map.getCenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setCenter(lnglat: [number, number]): void {
|
||||||
|
this.map.setCenter(lnglat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPitch(): number {
|
||||||
|
return this.map.getPitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRotation(): number {
|
||||||
|
return this.map.getBearing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getBounds(): Bounds {
|
||||||
|
return this.map.getBounds().toArray() as Bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinZoom(): number {
|
||||||
|
return this.map.getMinZoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMaxZoom(): number {
|
||||||
|
return this.map.getMaxZoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setRotation(rotation: number): void {
|
||||||
|
this.map.setBearing(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public zoomIn(option?: any, eventData?: any): void {
|
||||||
|
this.map.zoomIn(option, eventData);
|
||||||
|
}
|
||||||
|
public zoomOut(option?: any, eventData?: any): void {
|
||||||
|
this.map.zoomOut(option, eventData);
|
||||||
|
}
|
||||||
|
public setPitch(pitch: number) {
|
||||||
|
return this.map.setPitch(pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public panTo(p: [number, number]): void {
|
||||||
|
this.map.panTo(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public panBy(x: number = 0, y: number = 0): void {
|
||||||
|
this.panTo([x, y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public fitBounds(bound: Bounds, fitBoundsOptions?: any): void {
|
||||||
|
this.map.fitBounds(bound, fitBoundsOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMaxZoom(max: number): void {
|
||||||
|
this.map.setMaxZoom(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMinZoom(min: number): void {
|
||||||
|
this.map.setMinZoom(min);
|
||||||
|
}
|
||||||
|
public setMapStatus(option: Partial<IStatusOptions>): void {
|
||||||
|
if (option.doubleClickZoom === true) {
|
||||||
|
this.map.doubleClickZoom.enable();
|
||||||
|
}
|
||||||
|
if (option.doubleClickZoom === false) {
|
||||||
|
this.map.doubleClickZoom.disable();
|
||||||
|
}
|
||||||
|
if (option.dragEnable === false) {
|
||||||
|
this.map.dragPan.disable();
|
||||||
|
}
|
||||||
|
if (option.dragEnable === true) {
|
||||||
|
this.map.dragPan.enable();
|
||||||
|
}
|
||||||
|
if (option.rotateEnable === false) {
|
||||||
|
this.map.dragRotate.disable();
|
||||||
|
}
|
||||||
|
if (option.dragEnable === true) {
|
||||||
|
this.map.dragRotate.enable();
|
||||||
|
}
|
||||||
|
if (option.keyboardEnable === false) {
|
||||||
|
this.map.keyboard.disable();
|
||||||
|
}
|
||||||
|
if (option.keyboardEnable === true) {
|
||||||
|
this.map.keyboard.enable();
|
||||||
|
}
|
||||||
|
if (option.zoomEnable === false) {
|
||||||
|
this.map.scrollZoom.disable();
|
||||||
|
}
|
||||||
|
if (option.zoomEnable === true) {
|
||||||
|
this.map.scrollZoom.enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
||||||
|
this.map.flyTo({
|
||||||
|
zoom,
|
||||||
|
center,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMapStyle(style: any): void {
|
||||||
|
this.map.setStyle(this.getMapStyle(style));
|
||||||
|
}
|
||||||
|
|
||||||
|
public meterToCoord(center: [number, number], outer: [number, number]) {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 计算像素坐标
|
||||||
|
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
||||||
|
return this.map.unproject(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
||||||
|
return this.map.project(lnglat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public containerToLngLat(pixel: [number, number]): ILngLat {
|
||||||
|
return this.map.unproject(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
||||||
|
return this.map.project(lnglat);
|
||||||
|
}
|
||||||
|
public abstract lngLatToMercator(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
): IMercator;
|
||||||
|
|
||||||
|
public abstract getModelMatrix(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
rotate: [number, number, number],
|
||||||
|
scale: [number, number, number],
|
||||||
|
origin: IMercator,
|
||||||
|
): number[];
|
||||||
|
|
||||||
|
public abstract init(): Promise<void>;
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
this.eventEmitter.removeAllListeners();
|
||||||
|
if (this.map) {
|
||||||
|
this.map.remove();
|
||||||
|
this.$mapContainer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public emit(name: string, ...args: any[]) {
|
||||||
|
this.eventEmitter.emit(name, ...args);
|
||||||
|
}
|
||||||
|
public once(name: string, ...args: any[]) {
|
||||||
|
this.eventEmitter.once(name, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapContainer() {
|
||||||
|
return this.$mapContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public exportMap(type: 'jpg' | 'png'): string {
|
||||||
|
const renderCanvas = this.map.getCanvas();
|
||||||
|
const layersPng =
|
||||||
|
type === 'jpg'
|
||||||
|
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
||||||
|
: (renderCanvas?.toDataURL('image/png') as string);
|
||||||
|
return layersPng;
|
||||||
|
}
|
||||||
|
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||||
|
this.cameraChangedCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleCameraChanged = (e?: any) => {
|
||||||
|
const { lat, lng } = this.map.getCenter();
|
||||||
|
// Tip: 统一触发地图变化事件
|
||||||
|
this.emit('mapchange');
|
||||||
|
// resync
|
||||||
|
(this.viewport as IViewport).syncWithMapCamera({
|
||||||
|
bearing: this.map.getBearing(),
|
||||||
|
center: [lng, lat],
|
||||||
|
viewportHeight: this.map.transform.height,
|
||||||
|
pitch: this.map.getPitch(),
|
||||||
|
viewportWidth: this.map.transform.width,
|
||||||
|
zoom: this.map.getZoom(),
|
||||||
|
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
||||||
|
cameraHeight: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateCoordinateSystemService();
|
||||||
|
this.cameraChangedCallback(this.viewport as IViewport);
|
||||||
|
};
|
||||||
|
|
||||||
|
protected creatMapContainer(id: string | HTMLDivElement) {
|
||||||
|
let $wrapper = id as HTMLDivElement;
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
$wrapper = document.getElementById(id) as HTMLDivElement;
|
||||||
|
}
|
||||||
|
return $wrapper;
|
||||||
|
}
|
||||||
|
public updateView(viewOption: Partial<IMapCamera>) {
|
||||||
|
// Tip: 统一触发地图变化事件
|
||||||
|
this.emit('mapchange');
|
||||||
|
// resync
|
||||||
|
(this.viewport as IViewport).syncWithMapCamera({
|
||||||
|
bearing: viewOption.bearing,
|
||||||
|
center: viewOption.center,
|
||||||
|
viewportHeight: viewOption.viewportHeight,
|
||||||
|
pitch: viewOption.pitch,
|
||||||
|
viewportWidth: viewOption.viewportWidth,
|
||||||
|
zoom: viewOption.zoom,
|
||||||
|
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
||||||
|
cameraHeight: 0,
|
||||||
|
});
|
||||||
|
this.updateCoordinateSystemService();
|
||||||
|
this.cameraChangedCallback(this.viewport as IViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateCoordinateSystemService() {
|
||||||
|
const { offsetCoordinate = true } = this.config;
|
||||||
|
// set coordinate system
|
||||||
|
if (
|
||||||
|
(this.viewport as IViewport).getZoom() > LNGLAT_OFFSET_ZOOM_THRESHOLD &&
|
||||||
|
offsetCoordinate
|
||||||
|
) {
|
||||||
|
this.coordinateSystemService.setCoordinateSystem(
|
||||||
|
CoordinateSystem.LNGLAT_OFFSET,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.LNGLAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getMapStyle(name: MapStyle) {
|
||||||
|
if (typeof name !== 'string') {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
return MapTheme[name] ? MapTheme[name] : name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,15 +23,6 @@ export default class BaseMapWrapper<RawMap> implements IMapWrapper {
|
||||||
canvas?: HTMLCanvasElement,
|
canvas?: HTMLCanvasElement,
|
||||||
hasBaseMap?: boolean,
|
hasBaseMap?: boolean,
|
||||||
) {
|
) {
|
||||||
// // 首先使用全局配置服务校验地图参数
|
|
||||||
// const { valid, errorText } = this.configService.validateMapConfig(
|
|
||||||
// this.config,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if (!valid) {
|
|
||||||
// this.logger.error(errorText || '');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// 绑定用户传入的原始地图参数
|
// 绑定用户传入的原始地图参数
|
||||||
sceneContainer.bind<Partial<IMapConfig>>(TYPES.MapConfig).toConstantValue({
|
sceneContainer.bind<Partial<IMapConfig>>(TYPES.MapConfig).toConstantValue({
|
||||||
...this.config,
|
...this.config,
|
|
@ -2,7 +2,7 @@ import { IMapCamera, IViewport } from '@antv/l7-core';
|
||||||
import WebMercatorViewport from 'viewport-mercator-project';
|
import WebMercatorViewport from 'viewport-mercator-project';
|
||||||
|
|
||||||
export default class Viewport implements IViewport {
|
export default class Viewport implements IViewport {
|
||||||
private viewport: WebMercatorViewport;
|
public viewport: WebMercatorViewport;
|
||||||
|
|
||||||
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
||||||
const {
|
const {
|
||||||
|
@ -14,11 +14,24 @@ export default class Viewport implements IViewport {
|
||||||
viewportWidth,
|
viewportWidth,
|
||||||
} = mapCamera;
|
} = mapCamera;
|
||||||
|
|
||||||
|
const preView = this.viewport
|
||||||
|
? {
|
||||||
|
width: this.viewport.width,
|
||||||
|
height: this.viewport.height,
|
||||||
|
longitude: this.viewport.center[0],
|
||||||
|
latitude: this.viewport.center[1],
|
||||||
|
zoom: this.viewport.zoom,
|
||||||
|
pitch: this.viewport.pitch,
|
||||||
|
bearing: this.viewport.bearing,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deck.gl 使用的也是 Mapbox 同步相机,相机参数保持一致
|
* Deck.gl 使用的也是 Mapbox 同步相机,相机参数保持一致
|
||||||
* 例如相机高度固定为 height * 1.5,因此不需要传
|
* 例如相机高度固定为 height * 1.5,因此不需要传
|
||||||
*/
|
*/
|
||||||
this.viewport = new WebMercatorViewport({
|
this.viewport = new WebMercatorViewport({
|
||||||
|
...preView,
|
||||||
width: viewportWidth,
|
width: viewportWidth,
|
||||||
height: viewportHeight,
|
height: viewportHeight,
|
||||||
longitude: center && center[0],
|
longitude: center && center[0],
|
|
@ -0,0 +1,559 @@
|
||||||
|
/**
|
||||||
|
* AMapService
|
||||||
|
*/
|
||||||
|
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||||
|
import {
|
||||||
|
Bounds,
|
||||||
|
CoordinateSystem,
|
||||||
|
ICameraOptions,
|
||||||
|
ICoordinateSystemService,
|
||||||
|
IGlobalConfigService,
|
||||||
|
ILngLat,
|
||||||
|
IMapConfig,
|
||||||
|
IMapService,
|
||||||
|
IMercator,
|
||||||
|
IPoint,
|
||||||
|
IStatusOptions,
|
||||||
|
IViewport,
|
||||||
|
MapServiceEvent,
|
||||||
|
TYPES,
|
||||||
|
IMapCamera,
|
||||||
|
} from '@antv/l7-core';
|
||||||
|
import { DOM } from '@antv/l7-utils';
|
||||||
|
import { mat4, vec3 } from 'gl-matrix';
|
||||||
|
import { inject, injectable } from 'inversify';
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import { IAMapEvent, IAMapInstance } from '../../../typings/index';
|
||||||
|
import { ISimpleMapCoord, SimpleMapCoord } from '../simpleMapCoord';
|
||||||
|
import { toPaddingOptions } from '../utils';
|
||||||
|
import { Version } from '../../version';
|
||||||
|
import Viewport from '../Viewport';
|
||||||
|
import './logo.css';
|
||||||
|
import { MapTheme } from './theme';
|
||||||
|
let mapdivCount = 0;
|
||||||
|
// @ts-ignore
|
||||||
|
window.forceWebGL = true;
|
||||||
|
|
||||||
|
const AMAP_API_KEY: string = '15cd8a57710d40c9b7c0e3cc120f1200';
|
||||||
|
const AMAP_VERSION: string = '1.4.15';
|
||||||
|
/**
|
||||||
|
* 确保多个场景只引入一个高德地图脚本
|
||||||
|
*/
|
||||||
|
const AMAP_SCRIPT_ID: string = 'amap-script';
|
||||||
|
/**
|
||||||
|
* 高德地图脚本是否加载完毕
|
||||||
|
*/
|
||||||
|
let amapLoaded = false;
|
||||||
|
/**
|
||||||
|
* 高德地图脚本加载成功等待队列,成功之后依次触发
|
||||||
|
*/
|
||||||
|
let pendingResolveQueue: Array<() => void> = [];
|
||||||
|
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; // 暂时关闭 fix 统一不同坐标系,不同底图的高度位置
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMapService
|
||||||
|
*/
|
||||||
|
@injectable()
|
||||||
|
export default class AMapBaseService
|
||||||
|
implements IMapService<AMap.Map & IAMapInstance> {
|
||||||
|
public version: string = Version['GAODE1.x'];
|
||||||
|
public simpleMapCoord: ISimpleMapCoord = new SimpleMapCoord();
|
||||||
|
/**
|
||||||
|
* 原始地图实例
|
||||||
|
*/
|
||||||
|
public map: AMap.Map & IAMapInstance;
|
||||||
|
|
||||||
|
// 背景色
|
||||||
|
public bgColor: string = 'rgba(0, 0, 0, 0)';
|
||||||
|
|
||||||
|
@inject(TYPES.IGlobalConfigService)
|
||||||
|
protected readonly configService: IGlobalConfigService;
|
||||||
|
|
||||||
|
@inject(TYPES.MapConfig)
|
||||||
|
protected readonly config: Partial<IMapConfig>;
|
||||||
|
|
||||||
|
@inject(TYPES.ICoordinateSystemService)
|
||||||
|
protected readonly coordinateSystemService: ICoordinateSystemService;
|
||||||
|
|
||||||
|
@inject(TYPES.IEventEmitter)
|
||||||
|
protected eventEmitter: any;
|
||||||
|
|
||||||
|
protected markerContainer: HTMLElement;
|
||||||
|
protected $mapContainer: HTMLElement | null;
|
||||||
|
|
||||||
|
protected viewport: IViewport;
|
||||||
|
|
||||||
|
protected cameraChangedCallback: (viewport: IViewport) => void;
|
||||||
|
public setBgColor(color: string) {
|
||||||
|
this.bgColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addMarkerContainer(): void {
|
||||||
|
const mapContainer = this.map.getContainer();
|
||||||
|
if (mapContainer !== null) {
|
||||||
|
const amap = mapContainer.getElementsByClassName(
|
||||||
|
'amap-maps',
|
||||||
|
)[0] as HTMLElement;
|
||||||
|
this.markerContainer = DOM.create('div', 'l7-marker-container', amap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public getMarkerContainer(): HTMLElement {
|
||||||
|
return this.markerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map event
|
||||||
|
public on(type: string, handler: (...args: any[]) => void): void {
|
||||||
|
if (MapServiceEvent.indexOf(type) !== -1) {
|
||||||
|
this.eventEmitter.on(type, handler);
|
||||||
|
} else {
|
||||||
|
this.map.on(type, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public off(type: string, handler: (...args: any[]) => void): void {
|
||||||
|
if (MapServiceEvent.indexOf(type) !== -1) {
|
||||||
|
this.eventEmitter.off(type, handler);
|
||||||
|
} else {
|
||||||
|
this.map.off(type, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getContainer(): HTMLElement | null {
|
||||||
|
return this.map.getContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapCanvasContainer(): HTMLElement {
|
||||||
|
return this.map
|
||||||
|
.getContainer()
|
||||||
|
?.getElementsByClassName('amap-maps')[0] as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSize(): [number, number] {
|
||||||
|
const size = this.map.getSize();
|
||||||
|
return [size.getWidth(), size.getHeight()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getType() {
|
||||||
|
return 'amap';
|
||||||
|
}
|
||||||
|
public getZoom(): number {
|
||||||
|
// 统一返回 Mapbox 缩放等级
|
||||||
|
return this.map.getZoom() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setZoom(zoom: number): void {
|
||||||
|
// 统一设置 Mapbox 缩放等级
|
||||||
|
return this.map.setZoom(zoom + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCenter(options?: ICameraOptions): ILngLat {
|
||||||
|
if (options?.padding) {
|
||||||
|
const originCenter = this.getCenter();
|
||||||
|
const [w, h] = this.getSize();
|
||||||
|
const padding = toPaddingOptions(options.padding);
|
||||||
|
const px = this.lngLatToPixel([originCenter.lng, originCenter.lat]);
|
||||||
|
const offsetPx = [
|
||||||
|
(padding.right - padding.left) / 2,
|
||||||
|
(padding.bottom - padding.top) / 2,
|
||||||
|
];
|
||||||
|
|
||||||
|
const newCenter = this.pixelToLngLat([
|
||||||
|
px.x - offsetPx[0],
|
||||||
|
px.y - offsetPx[1],
|
||||||
|
]);
|
||||||
|
return newCenter;
|
||||||
|
}
|
||||||
|
const center = this.map.getCenter();
|
||||||
|
return {
|
||||||
|
lng: center.getLng(),
|
||||||
|
lat: center.getLat(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public setCenter(lnglat: [number, number], options?: ICameraOptions): void {
|
||||||
|
if (options?.padding) {
|
||||||
|
const padding = toPaddingOptions(options.padding);
|
||||||
|
const px = this.lngLatToPixel(lnglat);
|
||||||
|
const offsetPx = [
|
||||||
|
(padding.right - padding.left) / 2,
|
||||||
|
(padding.bottom - padding.top) / 2,
|
||||||
|
];
|
||||||
|
const newCenter = this.pixelToLngLat([
|
||||||
|
px.x + offsetPx[0],
|
||||||
|
px.y + offsetPx[1],
|
||||||
|
]);
|
||||||
|
this.map.setCenter([newCenter.lng, newCenter.lat]);
|
||||||
|
} else {
|
||||||
|
this.map.setCenter(lnglat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public getPitch(): number {
|
||||||
|
return this.map.getPitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRotation(): number {
|
||||||
|
// 统一返回逆时针旋转角度
|
||||||
|
return 360 - this.map.getRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getBounds(): Bounds {
|
||||||
|
// @ts-ignore
|
||||||
|
const amapBound = this.map.getBounds().toBounds();
|
||||||
|
const NE = amapBound.getNorthEast();
|
||||||
|
const SW = amapBound.getSouthWest();
|
||||||
|
const center = this.getCenter();
|
||||||
|
const maxlng =
|
||||||
|
center.lng > NE.getLng() || center.lng < SW.getLng()
|
||||||
|
? 180 - NE.getLng()
|
||||||
|
: NE.getLng();
|
||||||
|
const minlng = center.lng < SW.getLng() ? SW.getLng() - 180 : SW.getLng();
|
||||||
|
// 兼容 Mapbox,统一返回西南、东北
|
||||||
|
return [
|
||||||
|
[minlng, SW.getLat()],
|
||||||
|
[maxlng, NE.getLat()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinZoom(): number {
|
||||||
|
const zooms = this.map.get('zooms') as [number, number];
|
||||||
|
return zooms[0] - 1;
|
||||||
|
}
|
||||||
|
public getMaxZoom(): number {
|
||||||
|
const zooms = this.map.get('zooms') as [number, number];
|
||||||
|
return zooms[1] - 1;
|
||||||
|
}
|
||||||
|
public setRotation(rotation: number): void {
|
||||||
|
return this.map.setRotation(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPitch(pitch: number) {
|
||||||
|
return this.map.setPitch(pitch);
|
||||||
|
}
|
||||||
|
public zoomIn(): void {
|
||||||
|
this.map.zoomIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public zoomOut(): void {
|
||||||
|
this.map.zoomOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public panTo(p: [number, number]): void {
|
||||||
|
this.map.panTo(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public panBy(x: number = 0, y: number = 0): void {
|
||||||
|
this.map.panBy(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public fitBounds(extent: Bounds): void {
|
||||||
|
this.map.setBounds(
|
||||||
|
new AMap.Bounds([extent[0][0], extent[0][1], extent[1][0], extent[1][1]]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
||||||
|
this.map.setZoomAndCenter(zoom + 1, center);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMapStyle(style: string): void {
|
||||||
|
this.map.setMapStyle(this.getMapStyle(style));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMapStatus(option: Partial<IStatusOptions>): void {
|
||||||
|
this.map.setStatus(option);
|
||||||
|
}
|
||||||
|
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
||||||
|
const lngLat = this.map.pixelToLngLat(new AMap.Pixel(pixel[0], pixel[1]));
|
||||||
|
return { lng: lngLat.getLng(), lat: lngLat.getLat() };
|
||||||
|
}
|
||||||
|
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
||||||
|
const p = this.map.lnglatToPixel(new AMap.LngLat(lnglat[0], lnglat[1]));
|
||||||
|
return {
|
||||||
|
x: p.getX(),
|
||||||
|
y: p.getY(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public containerToLngLat(pixel: [number, number]): ILngLat {
|
||||||
|
const ll = new AMap.Pixel(pixel[0], pixel[1]);
|
||||||
|
const lngLat = this.map.containerToLngLat(ll);
|
||||||
|
return {
|
||||||
|
lng: lngLat?.getLng(),
|
||||||
|
lat: lngLat?.getLat(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
||||||
|
const ll = new AMap.LngLat(lnglat[0], lnglat[1]);
|
||||||
|
const pixel = this.map.lngLatToContainer(ll);
|
||||||
|
return {
|
||||||
|
x: pixel.getX(),
|
||||||
|
y: pixel.getY(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public lngLatToCoord(lnglat: [number, number]): any {
|
||||||
|
// @ts-ignore
|
||||||
|
const { x, y } = this.map.lngLatToGeodeticCoord(lnglat);
|
||||||
|
return [x, -y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public lngLatToMercator(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
): IMercator {
|
||||||
|
return {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getModelMatrix(
|
||||||
|
lnglat: [number, number],
|
||||||
|
altitude: number,
|
||||||
|
rotate: [number, number, number],
|
||||||
|
scale: [number, number, number] = [1, 1, 1],
|
||||||
|
|
||||||
|
): number[] {
|
||||||
|
const flat = this.viewport.projectFlat(lnglat);
|
||||||
|
// @ts-ignore
|
||||||
|
const modelMatrix = mat4.create();
|
||||||
|
|
||||||
|
mat4.translate(
|
||||||
|
modelMatrix,
|
||||||
|
modelMatrix,
|
||||||
|
vec3.fromValues(flat[0], flat[1], altitude),
|
||||||
|
);
|
||||||
|
mat4.scale(
|
||||||
|
modelMatrix,
|
||||||
|
modelMatrix,
|
||||||
|
vec3.fromValues(scale[0], scale[1], scale[2]),
|
||||||
|
);
|
||||||
|
|
||||||
|
mat4.rotateX(modelMatrix, modelMatrix, rotate[0]);
|
||||||
|
mat4.rotateY(modelMatrix, modelMatrix, rotate[1]);
|
||||||
|
mat4.rotateZ(modelMatrix, modelMatrix, rotate[2]);
|
||||||
|
|
||||||
|
return (modelMatrix as unknown) as number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
public async init(): Promise<void> {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
style = 'light',
|
||||||
|
minZoom = 0,
|
||||||
|
maxZoom = 18,
|
||||||
|
token = AMAP_API_KEY,
|
||||||
|
mapInstance,
|
||||||
|
plugin = [],
|
||||||
|
...rest
|
||||||
|
} = this.config;
|
||||||
|
// 高德地图创建独立的container;
|
||||||
|
// tslint:disable-next-line:typedef
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
const resolveMap = () => {
|
||||||
|
if (mapInstance) {
|
||||||
|
this.map = mapInstance as AMap.Map & IAMapInstance;
|
||||||
|
this.$mapContainer = this.map.getContainer();
|
||||||
|
setTimeout(() => {
|
||||||
|
this.map.on('camerachange', this.handleCameraChanged);
|
||||||
|
resolve();
|
||||||
|
}, 30);
|
||||||
|
} else {
|
||||||
|
this.$mapContainer = this.creatMapContainer(
|
||||||
|
id as string | HTMLDivElement,
|
||||||
|
);
|
||||||
|
const mapConstructorOptions = {
|
||||||
|
mapStyle: this.getMapStyle(style as string),
|
||||||
|
zooms: [minZoom, maxZoom],
|
||||||
|
viewMode: '3D',
|
||||||
|
...rest,
|
||||||
|
};
|
||||||
|
if (mapConstructorOptions.zoom) {
|
||||||
|
// TODO: 高德地图在相同大小下需要比 MapBox 多一个 zoom 层级
|
||||||
|
mapConstructorOptions.zoom += 1;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const map = new AMap.Map(this.$mapContainer, mapConstructorOptions);
|
||||||
|
// 监听地图相机事件
|
||||||
|
map.on('camerachange', this.handleCameraChanged);
|
||||||
|
// Tip: 为了兼容开启 MultiPassRender 的情况
|
||||||
|
// 修复 MultiPassRender 在高德地图 1.x 的情况下,缩放地图改变 zoom 时存在可视化层和底图不同步的现象
|
||||||
|
map.on('camerachange', () => {
|
||||||
|
setTimeout(() => this.handleAfterMapChange());
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
this.map = map;
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!amapLoaded && !mapInstance) {
|
||||||
|
if (token === AMAP_API_KEY) {
|
||||||
|
console.warn(this.configService.getSceneWarninfo('MapToken'));
|
||||||
|
}
|
||||||
|
amapLoaded = true;
|
||||||
|
plugin.push('Map3D');
|
||||||
|
AMapLoader.load({
|
||||||
|
key: token, // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||||
|
version: AMAP_VERSION, // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||||
|
plugins: plugin, // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
||||||
|
})
|
||||||
|
.then((AMap) => {
|
||||||
|
resolveMap();
|
||||||
|
|
||||||
|
if (pendingResolveQueue.length) {
|
||||||
|
pendingResolveQueue.forEach((r) => r());
|
||||||
|
pendingResolveQueue = [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
throw new Error(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if ((amapLoaded && window.AMap) || mapInstance) {
|
||||||
|
resolveMap();
|
||||||
|
} else {
|
||||||
|
pendingResolveQueue.push(resolveMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.viewport = new Viewport();
|
||||||
|
}
|
||||||
|
|
||||||
|
public meterToCoord(center: [number, number], outer: [number, number]) {
|
||||||
|
// 统一根据经纬度来转化
|
||||||
|
// Tip: 实际米距离 unit meter
|
||||||
|
const meterDis = AMap.GeometryUtil.distance(
|
||||||
|
new AMap.LngLat(...center),
|
||||||
|
new AMap.LngLat(...outer),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tip: 三维世界坐标距离
|
||||||
|
const [x1, y1] = this.lngLatToCoord(center);
|
||||||
|
const [x2, y2] = this.lngLatToCoord(outer);
|
||||||
|
const coordDis = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
||||||
|
|
||||||
|
return coordDis / meterDis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateView(viewOption: Partial<IMapCamera>): void {}
|
||||||
|
public getOverlayContainer(): HTMLElement | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public exportMap(type: 'jpg' | 'png'): string {
|
||||||
|
const renderCanvas = this.getContainer()?.getElementsByClassName(
|
||||||
|
'amap-layer',
|
||||||
|
)[0] as HTMLCanvasElement;
|
||||||
|
const layersPng =
|
||||||
|
type === 'jpg'
|
||||||
|
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
||||||
|
: (renderCanvas?.toDataURL('image/png') as string);
|
||||||
|
return layersPng;
|
||||||
|
}
|
||||||
|
|
||||||
|
public emit(name: string, ...args: any[]) {
|
||||||
|
this.eventEmitter.emit(name, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public once(name: string, ...args: any[]) {
|
||||||
|
this.eventEmitter.once(name, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
this.map.destroy();
|
||||||
|
|
||||||
|
// TODO: 销毁地图可视化层的容器
|
||||||
|
this.$mapContainer?.parentNode?.removeChild(this.$mapContainer);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
delete window.initAMap;
|
||||||
|
const $jsapi = document.getElementById(AMAP_SCRIPT_ID);
|
||||||
|
if ($jsapi) {
|
||||||
|
document.head.removeChild($jsapi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapContainer() {
|
||||||
|
return this.$mapContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||||
|
this.cameraChangedCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleAfterMapChange() {
|
||||||
|
this.emit('mapAfterFrameChange');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleCameraChanged = (e: IAMapEvent): void => {
|
||||||
|
const {
|
||||||
|
fov,
|
||||||
|
near,
|
||||||
|
far,
|
||||||
|
height,
|
||||||
|
pitch,
|
||||||
|
rotation,
|
||||||
|
aspect,
|
||||||
|
position,
|
||||||
|
} = e.camera;
|
||||||
|
const { lng, lat } = this.getCenter();
|
||||||
|
// Tip: 触发地图变化事件
|
||||||
|
this.emit('mapchange');
|
||||||
|
|
||||||
|
if (this.cameraChangedCallback) {
|
||||||
|
// resync viewport
|
||||||
|
// console.log('cameraHeight', height)
|
||||||
|
// console.log('pitch', pitch)
|
||||||
|
// console.log('rotation', rotation)
|
||||||
|
// console.log('zoom', this.map.getZoom())
|
||||||
|
this.viewport.syncWithMapCamera({
|
||||||
|
aspect,
|
||||||
|
// AMap 定义 rotation 为顺时针方向,而 Mapbox 为逆时针
|
||||||
|
// @see https://docs.mapbox.com/mapbox-gl-js/api/#map#getbearing
|
||||||
|
bearing: 360 - rotation,
|
||||||
|
far,
|
||||||
|
fov,
|
||||||
|
cameraHeight: height,
|
||||||
|
near,
|
||||||
|
pitch,
|
||||||
|
// AMap 定义的缩放等级 与 Mapbox 相差 1
|
||||||
|
zoom: this.map.getZoom() - 1,
|
||||||
|
center: [lng, lat],
|
||||||
|
offsetOrigin: [position.x, position.y],
|
||||||
|
});
|
||||||
|
const { offsetZoom = LNGLAT_OFFSET_ZOOM_THRESHOLD } = this.config;
|
||||||
|
// console.log('this.viewport', this.viewport)
|
||||||
|
// set coordinate system
|
||||||
|
if (this.viewport.getZoom() > offsetZoom) {
|
||||||
|
this.coordinateSystemService.setCoordinateSystem(
|
||||||
|
CoordinateSystem.P20_OFFSET,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20);
|
||||||
|
}
|
||||||
|
this.cameraChangedCallback(this.viewport);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected getMapStyle(name: string): string {
|
||||||
|
return MapTheme[name] ? MapTheme[name] : name;
|
||||||
|
}
|
||||||
|
protected creatMapContainer(id: string | HTMLDivElement) {
|
||||||
|
let $wrapper = id as HTMLDivElement;
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
$wrapper = document.getElementById(id) as HTMLDivElement;
|
||||||
|
}
|
||||||
|
const $amapdiv = document.createElement('div');
|
||||||
|
$amapdiv.style.cssText += `
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
$amapdiv.id = 'l7_amap_div' + mapdivCount++;
|
||||||
|
$wrapper.appendChild($amapdiv);
|
||||||
|
return $amapdiv;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
import { IMapCamera, IViewport } from '@antv/l7-core';
|
||||||
|
import { mat4, vec3 } from 'gl-matrix';
|
||||||
|
|
||||||
|
const DEGREES_TO_RADIANS = Math.PI / 180;
|
||||||
|
|
||||||
|
export default class Viewport implements IViewport {
|
||||||
|
private projectionMatrix: mat4 = mat4.create();
|
||||||
|
private viewMatrix: mat4 = mat4.create();
|
||||||
|
private viewProjectionMatrix: mat4 = mat4.create();
|
||||||
|
private ViewProjectionMatrixUncentered: mat4 = mat4.create();
|
||||||
|
private viewUncenteredMatrix: mat4 = mat4.create();
|
||||||
|
private zoom: number;
|
||||||
|
private center: number[];
|
||||||
|
|
||||||
|
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
||||||
|
const {
|
||||||
|
zoom = 1,
|
||||||
|
pitch = 0,
|
||||||
|
bearing = 0,
|
||||||
|
center = [0, 0],
|
||||||
|
offsetOrigin = [0, 0],
|
||||||
|
cameraHeight = 1,
|
||||||
|
aspect = 1,
|
||||||
|
near = 0.1,
|
||||||
|
far = 1000,
|
||||||
|
fov = 0,
|
||||||
|
} = mapCamera;
|
||||||
|
this.zoom = zoom;
|
||||||
|
this.center = center;
|
||||||
|
|
||||||
|
const pitchInRadians = pitch * DEGREES_TO_RADIANS;
|
||||||
|
const rotationInRadians = (360 - bearing) * DEGREES_TO_RADIANS;
|
||||||
|
|
||||||
|
// 计算透视投影矩阵 projectionMatrix
|
||||||
|
mat4.perspective(this.projectionMatrix, fov, aspect, near, far);
|
||||||
|
// 计算相机矩阵 viewMatrix
|
||||||
|
const eye = vec3.fromValues(
|
||||||
|
cameraHeight * Math.sin(pitchInRadians) * Math.sin(rotationInRadians),
|
||||||
|
-cameraHeight * Math.sin(pitchInRadians) * Math.cos(rotationInRadians),
|
||||||
|
cameraHeight * Math.cos(pitchInRadians),
|
||||||
|
);
|
||||||
|
const up = vec3.fromValues(
|
||||||
|
-Math.cos(pitchInRadians) * Math.sin(rotationInRadians),
|
||||||
|
Math.cos(pitchInRadians) * Math.cos(rotationInRadians),
|
||||||
|
Math.sin(pitchInRadians),
|
||||||
|
);
|
||||||
|
mat4.lookAt(this.viewMatrix, eye, vec3.fromValues(0, 0, 0), up);
|
||||||
|
this.viewUncenteredMatrix = mat4.clone(this.viewMatrix);
|
||||||
|
|
||||||
|
// 移动相机位置
|
||||||
|
mat4.translate(
|
||||||
|
this.viewMatrix,
|
||||||
|
this.viewMatrix,
|
||||||
|
vec3.fromValues(-offsetOrigin[0], offsetOrigin[1], 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
mat4.multiply(
|
||||||
|
this.viewProjectionMatrix,
|
||||||
|
this.projectionMatrix,
|
||||||
|
this.viewMatrix,
|
||||||
|
);
|
||||||
|
mat4.multiply(
|
||||||
|
this.ViewProjectionMatrixUncentered,
|
||||||
|
this.projectionMatrix,
|
||||||
|
this.viewMatrix,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getZoom(): number {
|
||||||
|
return this.zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getZoomScale(): number {
|
||||||
|
// 512 尺寸下的缩放:2 ^ 19
|
||||||
|
return 524288;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCenter(): [number, number] {
|
||||||
|
const [lng, lat] = this.center;
|
||||||
|
return [lng, lat];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getProjectionMatrix(): number[] {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.projectionMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getModelMatrix(): number[] {
|
||||||
|
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getViewMatrix(): number[] {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.viewMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getViewMatrixUncentered(): number[] {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.viewUncenteredMatrix;
|
||||||
|
}
|
||||||
|
public getViewProjectionMatrix(): number[] {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.viewProjectionMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getViewProjectionMatrixUncentered(): number[] {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.ViewProjectionMatrixUncentered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFocalDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P20 坐标系,固定 scale
|
||||||
|
*/
|
||||||
|
public projectFlat(lngLat: [number, number]): [number, number] {
|
||||||
|
const maxs = 85.0511287798;
|
||||||
|
const lat = Math.max(Math.min(maxs, lngLat[1]), -maxs);
|
||||||
|
// tslint:disable-next-line:no-bitwise
|
||||||
|
const zoomScale = 256 << 20;
|
||||||
|
let d = Math.PI / 180;
|
||||||
|
let x = lngLat[0] * d;
|
||||||
|
let y = lat * d;
|
||||||
|
y = Math.log(Math.tan(Math.PI / 4 + y / 2));
|
||||||
|
const a = 0.5 / Math.PI;
|
||||||
|
const b = 0.5;
|
||||||
|
const c = -0.5 / Math.PI;
|
||||||
|
d = 0.5;
|
||||||
|
x = zoomScale * (a * x + b) - 215440491;
|
||||||
|
y = -(zoomScale * (c * y + d) - 106744817);
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
.amap-logo{
|
||||||
|
display: none !important;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const MapTheme: {
|
||||||
|
[key: string]: any;
|
||||||
|
} = {
|
||||||
|
dark: 'amap://styles/c9f1d10cae34f8ab05e425462c5a58d7?isPublic=true',
|
||||||
|
light: 'amap://styles/c422f5c0cfced5be9fe3a83f05f28a68?isPublic=true',
|
||||||
|
normal: 'amap://styles/normal',
|
||||||
|
blank: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true',
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
import Viewport from './Viewport';
|
||||||
|
import BaseMapWrapper from './BaseMapWrapper';
|
||||||
|
import BaseMapService from './BaseMapService';
|
||||||
|
export { Viewport, BaseMapWrapper, BaseMapService };
|
|
@ -0,0 +1,23 @@
|
||||||
|
export const MapTheme: {
|
||||||
|
[key: string]: any;
|
||||||
|
} = {
|
||||||
|
light: 'mapbox://styles/zcxduo/ck2ypyb1r3q9o1co1766dex29',
|
||||||
|
dark: 'mapbox://styles/zcxduo/ck241p6413s0b1cpayzldv7x7',
|
||||||
|
normal: 'mapbox://styles/mapbox/streets-v11',
|
||||||
|
blank: {
|
||||||
|
version: 8,
|
||||||
|
// sprite: 'https://lzxue.github.io/font-glyphs/sprite/sprite',
|
||||||
|
// glyphs:
|
||||||
|
// 'https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf',
|
||||||
|
sources: {},
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
id: 'background',
|
||||||
|
type: 'background',
|
||||||
|
layout: {
|
||||||
|
visibility: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
|
@ -42,5 +42,5 @@ export function toPaddingOptions(padding: IPadding = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.assign({},defaultPadding,padding)
|
return Object.assign({}, defaultPadding, padding);
|
||||||
}
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
"author": "lzxue",
|
"author": "lzxue",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/async-hook": "^2.1.0",
|
"@antv/async-hook": "^2.2.2",
|
||||||
"@antv/l7-core": "2.9.26",
|
"@antv/l7-core": "2.9.26",
|
||||||
"@antv/l7-utils": "2.9.26",
|
"@antv/l7-utils": "2.9.26",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
"@antv/l7-utils": ["packages/utils/src"],
|
"@antv/l7-utils": ["packages/utils/src"],
|
||||||
"@antv/l7-test-utils":["packages/test-utils/src"],
|
"@antv/l7-test-utils":["packages/test-utils/src"],
|
||||||
"@antv/l7": ["packages/l7/src"],
|
"@antv/l7": ["packages/l7/src"],
|
||||||
|
"@antv/l7-leaflet": ["packages/leaflet/src"],
|
||||||
"*": ["packages", "typings/*"]
|
"*": ["packages", "typings/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue