mirror of https://gitee.com/antv-l7/antv-l7
commit
091ea42031
|
@ -76,6 +76,19 @@ const scene = new L7.Scene({
|
|||
|
||||
需传入 dom 容器或者容器 id {domObject || string} [必选]
|
||||
|
||||
### logoPosition
|
||||
|
||||
L7 Logo 的显示位置 默认左下角
|
||||
|
||||
- bottomright
|
||||
- topright
|
||||
- bottomleft,
|
||||
- topleft`
|
||||
|
||||
### logoVisible
|
||||
|
||||
是否显示 L7 的 Logo {boolean} true
|
||||
|
||||
### zoom
|
||||
|
||||
地图初始显示级别 {number} (0-22)
|
||||
|
|
|
@ -76,6 +76,19 @@ const scene = new L7.Scene({
|
|||
|
||||
需传入 dom 容器或者容器 id {domObject || string} [必选]
|
||||
|
||||
### logoPosition
|
||||
|
||||
L7 Logo 的显示位置 默认左下角
|
||||
|
||||
- bottomright
|
||||
- topright
|
||||
- bottomleft,
|
||||
- topleft`
|
||||
|
||||
### logoVisible
|
||||
|
||||
是否显示 L7 的 Logo {boolean} true
|
||||
|
||||
### zoom
|
||||
|
||||
地图初始显示级别 {number} (0-22)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"message": "chore: publish"
|
||||
}
|
||||
},
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"publishConfig": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-component",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,8 +24,8 @@
|
|||
"author": "lzxue",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"inversify": "^5.0.1",
|
||||
|
|
|
@ -175,8 +175,12 @@ export default class Layers extends Control {
|
|||
for (let i = inputs.length - 1; i >= 0; i--) {
|
||||
input = inputs[i];
|
||||
layer = this.layerService.getLayer(input.layerId);
|
||||
if (layer) {
|
||||
input.disabled = !layer.inited || !layer.isVisible();
|
||||
|
||||
if (layer && layer.inited) {
|
||||
const minZoom = layer.getMinZoom();
|
||||
const maxZoom = layer.getMaxZoom();
|
||||
|
||||
input.disabled = zoom < minZoom || zoom > maxZoom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-core",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -22,7 +22,7 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/tiny-sdf": "^1.1.1",
|
||||
"ajv": "^6.10.2",
|
||||
|
|
|
@ -12,6 +12,8 @@ import WarnInfo, { IWarnInfo } from './warnInfo';
|
|||
*/
|
||||
const defaultSceneConfig: Partial<ISceneConfig> = {
|
||||
id: 'map',
|
||||
logoPosition: 'bottomleft',
|
||||
logoVisible: true,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import Ajv from 'ajv';
|
||||
import { PositionName } from '../component/IControlService';
|
||||
import { ILayerConfig } from '../layer/ILayerService';
|
||||
import { IMapWrapper } from '../map/IMapService';
|
||||
import { IRenderConfig } from '../renderer/IRendererService';
|
||||
|
||||
export interface ISceneConfig extends IRenderConfig {
|
||||
id: string | HTMLDivElement;
|
||||
map: IMapWrapper;
|
||||
logoPosition?: PositionName;
|
||||
logoVisible?: boolean;
|
||||
}
|
||||
|
||||
interface IValidateResult {
|
||||
|
|
|
@ -141,6 +141,9 @@ export interface ILayer {
|
|||
isVisible(): boolean;
|
||||
setMaxZoom(min: number): ILayer;
|
||||
setMinZoom(max: number): ILayer;
|
||||
getMinZoom(): number;
|
||||
getMaxZoom(): number;
|
||||
get(name: string): number;
|
||||
setBlend(type: keyof typeof BlendType): void;
|
||||
// animate(field: string, option: any): ILayer;
|
||||
render(): ILayer;
|
||||
|
|
|
@ -10,7 +10,7 @@ export interface ISceneService {
|
|||
addLayer(layer: ILayer): void;
|
||||
render(): void;
|
||||
getSceneContainer(): HTMLDivElement;
|
||||
ExportMap2Png(): string;
|
||||
exportPng(): string;
|
||||
destroy(): void;
|
||||
}
|
||||
// scene 事件
|
||||
|
|
|
@ -226,10 +226,11 @@ export default class Scene extends EventEmitter implements ISceneService {
|
|||
return this.$container as HTMLDivElement;
|
||||
}
|
||||
|
||||
public ExportMap2Png(): string {
|
||||
public exportPng(): string {
|
||||
const renderCanvas = this.$container?.getElementsByTagName('canvas')[0];
|
||||
this.render();
|
||||
const layersPng = renderCanvas?.toDataURL() as string;
|
||||
// this.render();
|
||||
DOM.printCanvas(renderCanvas as HTMLCanvasElement);
|
||||
const layersPng = renderCanvas?.toDataURL('image/png') as string;
|
||||
return layersPng;
|
||||
}
|
||||
|
||||
|
@ -237,11 +238,11 @@ export default class Scene extends EventEmitter implements ISceneService {
|
|||
this.emit('destroy');
|
||||
this.inited = false;
|
||||
this.layerService.destroy();
|
||||
this.rendererService.destroy();
|
||||
this.interactionService.destroy();
|
||||
this.controlService.destroy();
|
||||
this.markerService.destroy();
|
||||
this.removeAllListeners();
|
||||
this.rendererService.destroy();
|
||||
this.map.destroy();
|
||||
unbind(this.$container as HTMLDivElement, this.handleWindowResized);
|
||||
window
|
||||
|
|
|
@ -16,11 +16,11 @@ vec4 filterHighlightColor(vec4 color) {
|
|||
if (selected) {
|
||||
vec4 highLightColor = u_HighlightColor * COLOR_SCALE;
|
||||
|
||||
// float highLightAlpha = highLightColor.a;
|
||||
// float highLightRatio = highLightAlpha / (highLightAlpha + color.a * (1.0 - highLightAlpha));
|
||||
float highLightAlpha = highLightColor.a;
|
||||
float highLightRatio = highLightAlpha / (highLightAlpha + color.a * (1.0 - highLightAlpha));
|
||||
|
||||
// vec3 resultRGB = mix(color.rgb, highLightColor.rgb, highLightRatio);
|
||||
return highLightColor;
|
||||
vec3 resultRGB = mix(color.rgb, highLightColor.rgb, highLightRatio);
|
||||
return vec4(resultRGB, color.a);
|
||||
} else {
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,11 +24,11 @@
|
|||
"author": "antv",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@antv/l7-component": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-layers": "^2.0.13",
|
||||
"@antv/l7-maps": "^2.0.13",
|
||||
"@antv/l7-scene": "^2.0.13",
|
||||
"@antv/l7-component": "^2.0.14",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-layers": "^2.0.14",
|
||||
"@antv/l7-maps": "^2.0.14",
|
||||
"@antv/l7-scene": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7"
|
||||
},
|
||||
"gitHead": "9fabb78790428d2025b89fb6146fc555cb1d987d",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-layers",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "L7's collection of built-in layers",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -22,13 +22,12 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-source": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-source": "^2.0.14",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/martini": "^0.1.0",
|
||||
"@turf/meta": "^6.0.2",
|
||||
"@types/d3-color": "^1.2.2",
|
||||
"d3-array": "^2.3.1",
|
||||
"d3-color": "^1.4.0",
|
||||
"d3-scale": "^3.1.0",
|
||||
|
@ -47,7 +46,8 @@
|
|||
"@types/d3-scale": "^2.1.1",
|
||||
"@types/earcut": "^2.1.0",
|
||||
"@types/gl-matrix": "^2.4.5",
|
||||
"@types/lodash": "^4.14.138"
|
||||
"@types/lodash": "^4.14.138",
|
||||
"@types/d3-color": "^1.2.2"
|
||||
},
|
||||
"gitHead": "9fabb78790428d2025b89fb6146fc555cb1d987d",
|
||||
"publishConfig": {
|
||||
|
|
|
@ -629,6 +629,22 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
return this;
|
||||
}
|
||||
|
||||
public getMinZoom(): number {
|
||||
const { minZoom } = this.getLayerConfig();
|
||||
return minZoom as number;
|
||||
}
|
||||
|
||||
public getMaxZoom(): number {
|
||||
const { maxZoom } = this.getLayerConfig();
|
||||
return maxZoom as number;
|
||||
}
|
||||
|
||||
public get(name: string) {
|
||||
const cfg = this.getLayerConfig();
|
||||
// @ts-ignore
|
||||
return cfg[name];
|
||||
}
|
||||
|
||||
public setMaxZoom(maxZoom: number): ILayer {
|
||||
this.updateLayerConfig({
|
||||
maxZoom,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-maps",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,8 +23,8 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"gl-matrix": "^3.1.0",
|
||||
"inversify": "^5.0.1",
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { IAMapInstance } from '../../typings/index';
|
||||
import BaseMapWrapper from '../BaseMapWrapper';
|
||||
import AMapService from './index';
|
||||
|
||||
export default class AMapWrapper extends BaseMapWrapper<
|
||||
AMap.Map & IAMapInstance
|
||||
> {
|
||||
protected getServiceConstructor() {
|
||||
return AMapService;
|
||||
}
|
||||
}
|
|
@ -1,393 +1,11 @@
|
|||
/**
|
||||
* AMapService
|
||||
*/
|
||||
import {
|
||||
Bounds,
|
||||
CoordinateSystem,
|
||||
ICoordinateSystemService,
|
||||
IGlobalConfigService,
|
||||
ILngLat,
|
||||
ILogService,
|
||||
IMapConfig,
|
||||
IMapService,
|
||||
IPoint,
|
||||
IViewport,
|
||||
MapServiceEvent,
|
||||
MapStyle,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import { DOM } from '@antv/l7-utils';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { IAMapEvent, IAMapInstance } from '../../typings/index';
|
||||
import { MapTheme } from './theme';
|
||||
import Viewport from './Viewport';
|
||||
let mapdivCount = 0;
|
||||
import { IAMapInstance } from '../../typings/index';
|
||||
import BaseMapWrapper from '../BaseMapWrapper';
|
||||
import AMapService from './map';
|
||||
|
||||
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 AMapService
|
||||
implements IMapService<AMap.Map & IAMapInstance> {
|
||||
/**
|
||||
* 原始地图实例
|
||||
*/
|
||||
public map: AMap.Map & IAMapInstance;
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
@inject(TYPES.ILogService)
|
||||
private readonly logger: ILogService;
|
||||
|
||||
@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 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 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 {
|
||||
return this.map.setZoom(zoom);
|
||||
}
|
||||
|
||||
public getCenter(): ILngLat {
|
||||
const center = this.map.getCenter();
|
||||
return {
|
||||
lng: center.getLng(),
|
||||
lat: center.getLat(),
|
||||
};
|
||||
}
|
||||
|
||||
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 zoomIn(): void {
|
||||
this.map.zoomIn();
|
||||
}
|
||||
|
||||
public zoomOut(): void {
|
||||
this.map.zoomOut();
|
||||
}
|
||||
|
||||
public panTo(p: [number, number]): void {
|
||||
this.map.panTo(p);
|
||||
}
|
||||
public panBy(pixel: [number, number]): void {
|
||||
this.map.panTo(pixel);
|
||||
}
|
||||
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, center);
|
||||
}
|
||||
public setMapStyle(style: string): void {
|
||||
this.map.setMapStyle(this.getMapStyle(style));
|
||||
}
|
||||
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 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((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.creatAmapContainer(
|
||||
id as string | HTMLDivElement,
|
||||
);
|
||||
|
||||
const map = new AMap.Map(this.$mapContainer, {
|
||||
mapStyle: this.getMapStyle(style as string),
|
||||
zooms: [minZoom, maxZoom],
|
||||
viewMode: '3D',
|
||||
...rest,
|
||||
});
|
||||
// 监听地图相机事件
|
||||
map.on('camerachange', this.handleCameraChanged);
|
||||
// @ts-ignore
|
||||
this.map = map;
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
if (!amapLoaded && !mapInstance) {
|
||||
if (token === AMAP_API_KEY) {
|
||||
this.logger.warn(this.configService.getSceneWarninfo('MapToken'));
|
||||
}
|
||||
amapLoaded = true;
|
||||
plugin.push('Map3D');
|
||||
this.loadAMapScript(
|
||||
`https://webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=${plugin.join(
|
||||
',',
|
||||
)}`,
|
||||
).then(() => {
|
||||
resolveMap();
|
||||
if (pendingResolveQueue.length) {
|
||||
pendingResolveQueue.forEach((r) => r());
|
||||
pendingResolveQueue = [];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if ((amapLoaded && window.AMap) || mapInstance) {
|
||||
resolveMap();
|
||||
} else {
|
||||
pendingResolveQueue.push(resolveMap);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.viewport = new Viewport();
|
||||
}
|
||||
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();
|
||||
// @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;
|
||||
}
|
||||
|
||||
private handleCameraChanged = (e: IAMapEvent): void => {
|
||||
const {
|
||||
fov,
|
||||
near,
|
||||
far,
|
||||
height,
|
||||
pitch,
|
||||
rotation,
|
||||
aspect,
|
||||
position,
|
||||
} = e.camera;
|
||||
const { lng, lat } = this.getCenter();
|
||||
if (this.cameraChangedCallback) {
|
||||
// resync viewport
|
||||
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],
|
||||
});
|
||||
|
||||
// set coordinate system
|
||||
if (this.viewport.getZoom() > LNGLAT_OFFSET_ZOOM_THRESHOLD) {
|
||||
this.coordinateSystemService.setCoordinateSystem(
|
||||
CoordinateSystem.P20_OFFSET,
|
||||
);
|
||||
} else {
|
||||
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20);
|
||||
}
|
||||
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;
|
||||
}
|
||||
private loadAMapScript(src: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => {
|
||||
resolve();
|
||||
};
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
export default class AMapWrapper extends BaseMapWrapper<
|
||||
AMap.Map & IAMapInstance
|
||||
> {
|
||||
protected getServiceConstructor() {
|
||||
return AMapService;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,393 @@
|
|||
/**
|
||||
* AMapService
|
||||
*/
|
||||
import {
|
||||
Bounds,
|
||||
CoordinateSystem,
|
||||
ICoordinateSystemService,
|
||||
IGlobalConfigService,
|
||||
ILngLat,
|
||||
ILogService,
|
||||
IMapConfig,
|
||||
IMapService,
|
||||
IPoint,
|
||||
IViewport,
|
||||
MapServiceEvent,
|
||||
MapStyle,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import { DOM } from '@antv/l7-utils';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { IAMapEvent, IAMapInstance } from '../../typings/index';
|
||||
import { MapTheme } from './theme';
|
||||
import Viewport from './Viewport';
|
||||
let mapdivCount = 0;
|
||||
|
||||
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 AMapService
|
||||
implements IMapService<AMap.Map & IAMapInstance> {
|
||||
/**
|
||||
* 原始地图实例
|
||||
*/
|
||||
public map: AMap.Map & IAMapInstance;
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
@inject(TYPES.ILogService)
|
||||
private readonly logger: ILogService;
|
||||
|
||||
@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 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 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 {
|
||||
return this.map.setZoom(zoom);
|
||||
}
|
||||
|
||||
public getCenter(): ILngLat {
|
||||
const center = this.map.getCenter();
|
||||
return {
|
||||
lng: center.getLng(),
|
||||
lat: center.getLat(),
|
||||
};
|
||||
}
|
||||
|
||||
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 zoomIn(): void {
|
||||
this.map.zoomIn();
|
||||
}
|
||||
|
||||
public zoomOut(): void {
|
||||
this.map.zoomOut();
|
||||
}
|
||||
|
||||
public panTo(p: [number, number]): void {
|
||||
this.map.panTo(p);
|
||||
}
|
||||
public panBy(pixel: [number, number]): void {
|
||||
this.map.panTo(pixel);
|
||||
}
|
||||
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, center);
|
||||
}
|
||||
public setMapStyle(style: string): void {
|
||||
this.map.setMapStyle(this.getMapStyle(style));
|
||||
}
|
||||
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 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((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.creatAmapContainer(
|
||||
id as string | HTMLDivElement,
|
||||
);
|
||||
|
||||
const map = new AMap.Map(this.$mapContainer, {
|
||||
mapStyle: this.getMapStyle(style as string),
|
||||
zooms: [minZoom, maxZoom],
|
||||
viewMode: '3D',
|
||||
...rest,
|
||||
});
|
||||
// 监听地图相机事件
|
||||
map.on('camerachange', this.handleCameraChanged);
|
||||
// @ts-ignore
|
||||
this.map = map;
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
if (!amapLoaded && !mapInstance) {
|
||||
if (token === AMAP_API_KEY) {
|
||||
this.logger.warn(this.configService.getSceneWarninfo('MapToken'));
|
||||
}
|
||||
amapLoaded = true;
|
||||
plugin.push('Map3D');
|
||||
this.loadAMapScript(
|
||||
`https://webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=${plugin.join(
|
||||
',',
|
||||
)}`,
|
||||
).then(() => {
|
||||
resolveMap();
|
||||
if (pendingResolveQueue.length) {
|
||||
pendingResolveQueue.forEach((r) => r());
|
||||
pendingResolveQueue = [];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if ((amapLoaded && window.AMap) || mapInstance) {
|
||||
resolveMap();
|
||||
} else {
|
||||
pendingResolveQueue.push(resolveMap);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.viewport = new Viewport();
|
||||
}
|
||||
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();
|
||||
// @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;
|
||||
}
|
||||
|
||||
private handleCameraChanged = (e: IAMapEvent): void => {
|
||||
const {
|
||||
fov,
|
||||
near,
|
||||
far,
|
||||
height,
|
||||
pitch,
|
||||
rotation,
|
||||
aspect,
|
||||
position,
|
||||
} = e.camera;
|
||||
const { lng, lat } = this.getCenter();
|
||||
if (this.cameraChangedCallback) {
|
||||
// resync viewport
|
||||
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],
|
||||
});
|
||||
|
||||
// set coordinate system
|
||||
if (this.viewport.getZoom() > LNGLAT_OFFSET_ZOOM_THRESHOLD) {
|
||||
this.coordinateSystemService.setCoordinateSystem(
|
||||
CoordinateSystem.P20_OFFSET,
|
||||
);
|
||||
} else {
|
||||
this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20);
|
||||
}
|
||||
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;
|
||||
}
|
||||
private loadAMapScript(src: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => {
|
||||
resolve();
|
||||
};
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import GaodeMap from './amap/Wrapper';
|
||||
import Mapbox from './mapbox/Wrapper';
|
||||
import GaodeMap from './amap/';
|
||||
import Mapbox from './mapbox/';
|
||||
|
||||
export { GaodeMap, Mapbox };
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import { Map } from 'mapbox-gl';
|
||||
import { IMapboxInstance } from '../../typings/index';
|
||||
import BaseMapWrapper from '../BaseMapWrapper';
|
||||
import MapboxService from './index';
|
||||
|
||||
export default class MapboxWrapper extends BaseMapWrapper<
|
||||
Map & IMapboxInstance
|
||||
> {
|
||||
protected getServiceConstructor() {
|
||||
return MapboxService;
|
||||
}
|
||||
}
|
|
@ -1,328 +1,12 @@
|
|||
/**
|
||||
* MapboxService
|
||||
*/
|
||||
import {
|
||||
Bounds,
|
||||
CoordinateSystem,
|
||||
ICoordinateSystemService,
|
||||
IGlobalConfigService,
|
||||
ILngLat,
|
||||
ILogService,
|
||||
IMapConfig,
|
||||
IMapService,
|
||||
IPoint,
|
||||
IViewport,
|
||||
MapServiceEvent,
|
||||
MapStyle,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import { DOM } from '@antv/l7-utils';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import mapboxgl, { IControl, Map } from 'mapbox-gl';
|
||||
import { Map } from 'mapbox-gl';
|
||||
import { IMapboxInstance } from '../../typings/index';
|
||||
import Viewport from './Viewport';
|
||||
const EventMap: {
|
||||
[key: string]: any;
|
||||
} = {
|
||||
mapmove: 'move',
|
||||
camerachange: 'move',
|
||||
};
|
||||
import { MapTheme } from './theme';
|
||||
import BaseMapWrapper from '../BaseMapWrapper';
|
||||
import MapboxService from './map';
|
||||
|
||||
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
||||
const MAPBOX_API_KEY =
|
||||
'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ';
|
||||
/**
|
||||
* AMapService
|
||||
*/
|
||||
@injectable()
|
||||
export default class MapboxService
|
||||
implements IMapService<Map & IMapboxInstance> {
|
||||
public map: Map & IMapboxInstance;
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
private readonly config: Partial<IMapConfig>;
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
@inject(TYPES.ILogService)
|
||||
private readonly logger: ILogService;
|
||||
@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;
|
||||
|
||||
// init
|
||||
public addMarkerContainer(): void {
|
||||
const container = this.map.getCanvasContainer();
|
||||
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public getContainer(): HTMLElement | null {
|
||||
return this.map.getContainer();
|
||||
}
|
||||
|
||||
public getSize(): [number, number] {
|
||||
const size = this.map.transform;
|
||||
return [size.width, size.height];
|
||||
}
|
||||
// get mapStatus method
|
||||
|
||||
public getType() {
|
||||
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 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(): void {
|
||||
this.map.zoomIn();
|
||||
}
|
||||
|
||||
public zoomOut(): void {
|
||||
this.map.zoomOut();
|
||||
}
|
||||
|
||||
public panTo(p: [number, number]): void {
|
||||
this.map.panTo(p);
|
||||
}
|
||||
|
||||
public panBy(pixel: [number, number]): void {
|
||||
this.panTo(pixel);
|
||||
}
|
||||
|
||||
public fitBounds(bound: Bounds): void {
|
||||
this.map.fitBounds(bound);
|
||||
}
|
||||
|
||||
public setMaxZoom(max: number): void {
|
||||
this.map.setMaxZoom(max);
|
||||
}
|
||||
|
||||
public setMinZoom(min: number): void {
|
||||
this.map.setMinZoom(min);
|
||||
}
|
||||
|
||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
||||
this.map.flyTo({
|
||||
zoom,
|
||||
center,
|
||||
});
|
||||
}
|
||||
|
||||
public setMapStyle(style: string): 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);
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
const {
|
||||
id = 'map',
|
||||
attributionControl = false,
|
||||
style = 'light',
|
||||
token = MAPBOX_API_KEY,
|
||||
rotation = 0,
|
||||
mapInstance,
|
||||
...rest
|
||||
} = this.config;
|
||||
|
||||
this.viewport = new Viewport();
|
||||
|
||||
/**
|
||||
* TODO: 使用 mapbox v0.53.x 版本 custom layer,需要共享 gl context
|
||||
* @see https://github.com/mapbox/mapbox-gl-js/blob/master/debug/threejs.html#L61-L64
|
||||
*/
|
||||
|
||||
// 判断全局 mapboxgl 对象的加载
|
||||
if (!mapInstance && !mapboxgl) {
|
||||
// 用户有时传递进来的实例是继承于 mapbox 实例化的,不一定是 mapboxgl 对象。
|
||||
this.logger.error(this.configService.getSceneWarninfo('SDK'));
|
||||
}
|
||||
|
||||
if (
|
||||
token === MAPBOX_API_KEY &&
|
||||
style !== 'blank' &&
|
||||
!mapboxgl.accessToken &&
|
||||
!mapInstance // 如果用户传递了 mapInstance,应该不去干预实例的 accessToken。
|
||||
) {
|
||||
this.logger.warn(this.configService.getSceneWarninfo('MapToken'));
|
||||
}
|
||||
|
||||
// 判断是否设置了 accessToken
|
||||
if (!mapInstance && !mapboxgl.accessToken) {
|
||||
// 用户有时传递进来的实例是继承于 mapbox 实例化的,不一定是 mapboxgl 对象。
|
||||
mapboxgl.accessToken = token;
|
||||
}
|
||||
|
||||
if (mapInstance) {
|
||||
// @ts-ignore
|
||||
this.map = mapInstance;
|
||||
this.$mapContainer = this.map.getContainer();
|
||||
} else {
|
||||
this.$mapContainer = this.creatAmapContainer(id);
|
||||
// @ts-ignore
|
||||
this.map = new mapboxgl.Map({
|
||||
container: id,
|
||||
style: this.getMapStyle(style),
|
||||
attributionControl,
|
||||
bearing: rotation,
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
this.map.on('load', this.handleCameraChanged);
|
||||
this.map.on('move', this.handleCameraChanged);
|
||||
|
||||
// 不同于高德地图,需要手动触发首次渲染
|
||||
this.handleCameraChanged();
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.eventEmitter.removeAllListeners();
|
||||
if (this.map) {
|
||||
this.map.remove();
|
||||
this.$mapContainer = null;
|
||||
this.removeLogoControl();
|
||||
}
|
||||
}
|
||||
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 onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||
this.cameraChangedCallback = callback;
|
||||
}
|
||||
|
||||
private handleCameraChanged = () => {
|
||||
// @see https://github.com/mapbox/mapbox-gl-js/issues/2572
|
||||
const { lat, lng } = this.map.getCenter().wrap();
|
||||
|
||||
// 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) {
|
||||
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 removeLogoControl(): void {
|
||||
// @ts-ignore
|
||||
const controls = this.map._controls as IControl[];
|
||||
const logoCtr = controls.find((ctr: IControl) => {
|
||||
if (ctr.hasOwnProperty('_updateLogo')) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (logoCtr) {
|
||||
this.map.removeControl(logoCtr);
|
||||
}
|
||||
}
|
||||
|
||||
private getMapStyle(name: MapStyle) {
|
||||
if (typeof name !== 'string') {
|
||||
return name;
|
||||
}
|
||||
return MapTheme[name] ? MapTheme[name] : name;
|
||||
export default class MapboxWrapper extends BaseMapWrapper<
|
||||
Map & IMapboxInstance
|
||||
> {
|
||||
protected getServiceConstructor() {
|
||||
return MapboxService;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,328 @@
|
|||
/**
|
||||
* MapboxService
|
||||
*/
|
||||
import {
|
||||
Bounds,
|
||||
CoordinateSystem,
|
||||
ICoordinateSystemService,
|
||||
IGlobalConfigService,
|
||||
ILngLat,
|
||||
ILogService,
|
||||
IMapConfig,
|
||||
IMapService,
|
||||
IPoint,
|
||||
IViewport,
|
||||
MapServiceEvent,
|
||||
MapStyle,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import { DOM } from '@antv/l7-utils';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import mapboxgl, { IControl, Map } from 'mapbox-gl';
|
||||
import { IMapboxInstance } from '../../typings/index';
|
||||
import Viewport from './Viewport';
|
||||
const EventMap: {
|
||||
[key: string]: any;
|
||||
} = {
|
||||
mapmove: 'move',
|
||||
camerachange: 'move',
|
||||
};
|
||||
import { MapTheme } from './theme';
|
||||
|
||||
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
||||
const MAPBOX_API_KEY =
|
||||
'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ';
|
||||
/**
|
||||
* AMapService
|
||||
*/
|
||||
@injectable()
|
||||
export default class MapboxService
|
||||
implements IMapService<Map & IMapboxInstance> {
|
||||
public map: Map & IMapboxInstance;
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
private readonly config: Partial<IMapConfig>;
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
@inject(TYPES.ILogService)
|
||||
private readonly logger: ILogService;
|
||||
@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;
|
||||
|
||||
// init
|
||||
public addMarkerContainer(): void {
|
||||
const container = this.map.getCanvasContainer();
|
||||
this.markerContainer = DOM.create('div', 'l7-marker-container', container);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public getContainer(): HTMLElement | null {
|
||||
return this.map.getContainer();
|
||||
}
|
||||
|
||||
public getSize(): [number, number] {
|
||||
const size = this.map.transform;
|
||||
return [size.width, size.height];
|
||||
}
|
||||
// get mapStatus method
|
||||
|
||||
public getType() {
|
||||
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 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(): void {
|
||||
this.map.zoomIn();
|
||||
}
|
||||
|
||||
public zoomOut(): void {
|
||||
this.map.zoomOut();
|
||||
}
|
||||
|
||||
public panTo(p: [number, number]): void {
|
||||
this.map.panTo(p);
|
||||
}
|
||||
|
||||
public panBy(pixel: [number, number]): void {
|
||||
this.panTo(pixel);
|
||||
}
|
||||
|
||||
public fitBounds(bound: Bounds): void {
|
||||
this.map.fitBounds(bound);
|
||||
}
|
||||
|
||||
public setMaxZoom(max: number): void {
|
||||
this.map.setMaxZoom(max);
|
||||
}
|
||||
|
||||
public setMinZoom(min: number): void {
|
||||
this.map.setMinZoom(min);
|
||||
}
|
||||
|
||||
public setZoomAndCenter(zoom: number, center: [number, number]): void {
|
||||
this.map.flyTo({
|
||||
zoom,
|
||||
center,
|
||||
});
|
||||
}
|
||||
|
||||
public setMapStyle(style: string): 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);
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
const {
|
||||
id = 'map',
|
||||
attributionControl = false,
|
||||
style = 'light',
|
||||
token = MAPBOX_API_KEY,
|
||||
rotation = 0,
|
||||
mapInstance,
|
||||
...rest
|
||||
} = this.config;
|
||||
|
||||
this.viewport = new Viewport();
|
||||
|
||||
/**
|
||||
* TODO: 使用 mapbox v0.53.x 版本 custom layer,需要共享 gl context
|
||||
* @see https://github.com/mapbox/mapbox-gl-js/blob/master/debug/threejs.html#L61-L64
|
||||
*/
|
||||
|
||||
// 判断全局 mapboxgl 对象的加载
|
||||
if (!mapInstance && !mapboxgl) {
|
||||
// 用户有时传递进来的实例是继承于 mapbox 实例化的,不一定是 mapboxgl 对象。
|
||||
this.logger.error(this.configService.getSceneWarninfo('SDK'));
|
||||
}
|
||||
|
||||
if (
|
||||
token === MAPBOX_API_KEY &&
|
||||
style !== 'blank' &&
|
||||
!mapboxgl.accessToken &&
|
||||
!mapInstance // 如果用户传递了 mapInstance,应该不去干预实例的 accessToken。
|
||||
) {
|
||||
this.logger.warn(this.configService.getSceneWarninfo('MapToken'));
|
||||
}
|
||||
|
||||
// 判断是否设置了 accessToken
|
||||
if (!mapInstance && !mapboxgl.accessToken) {
|
||||
// 用户有时传递进来的实例是继承于 mapbox 实例化的,不一定是 mapboxgl 对象。
|
||||
mapboxgl.accessToken = token;
|
||||
}
|
||||
|
||||
if (mapInstance) {
|
||||
// @ts-ignore
|
||||
this.map = mapInstance;
|
||||
this.$mapContainer = this.map.getContainer();
|
||||
} else {
|
||||
this.$mapContainer = this.creatAmapContainer(id);
|
||||
// @ts-ignore
|
||||
this.map = new mapboxgl.Map({
|
||||
container: id,
|
||||
style: this.getMapStyle(style),
|
||||
attributionControl,
|
||||
bearing: rotation,
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
this.map.on('load', this.handleCameraChanged);
|
||||
this.map.on('move', this.handleCameraChanged);
|
||||
|
||||
// 不同于高德地图,需要手动触发首次渲染
|
||||
this.handleCameraChanged();
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.eventEmitter.removeAllListeners();
|
||||
if (this.map) {
|
||||
this.map.remove();
|
||||
this.$mapContainer = null;
|
||||
this.removeLogoControl();
|
||||
}
|
||||
}
|
||||
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 onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||
this.cameraChangedCallback = callback;
|
||||
}
|
||||
|
||||
private handleCameraChanged = () => {
|
||||
// @see https://github.com/mapbox/mapbox-gl-js/issues/2572
|
||||
const { lat, lng } = this.map.getCenter().wrap();
|
||||
|
||||
// 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) {
|
||||
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 removeLogoControl(): void {
|
||||
// @ts-ignore
|
||||
const controls = this.map._controls as IControl[];
|
||||
const logoCtr = controls.find((ctr: IControl) => {
|
||||
if (ctr.hasOwnProperty('_updateLogo')) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (logoCtr) {
|
||||
this.map.removeControl(logoCtr);
|
||||
}
|
||||
}
|
||||
|
||||
private getMapStyle(name: MapStyle) {
|
||||
if (typeof name !== 'string') {
|
||||
return name;
|
||||
}
|
||||
return MapTheme[name] ? MapTheme[name] : name;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-renderer",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -25,7 +25,7 @@
|
|||
"gl": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"inversify": "^5.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-scene",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -22,11 +22,11 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-component": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-maps": "^2.0.13",
|
||||
"@antv/l7-renderer": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-component": "^2.0.14",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-maps": "^2.0.14",
|
||||
"@antv/l7-renderer": "^2.0.14",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"inversify": "^5.0.1",
|
||||
"mapbox-gl": "^1.2.1",
|
||||
|
|
|
@ -57,7 +57,7 @@ class Scene
|
|||
private container: Container;
|
||||
|
||||
public constructor(config: ISceneConfig) {
|
||||
const { id, map } = config;
|
||||
const { id, map, logoPosition, logoVisible } = config;
|
||||
|
||||
// 创建场景容器
|
||||
const sceneContainer = createSceneContainer();
|
||||
|
@ -93,14 +93,16 @@ class Scene
|
|||
// 初始化 scene
|
||||
this.sceneService.init(config);
|
||||
// TODO: 初始化组件
|
||||
this.addControl(new Logo());
|
||||
if (logoVisible) {
|
||||
this.addControl(new Logo({ position: logoPosition }));
|
||||
}
|
||||
}
|
||||
|
||||
public getMapService(): IMapService<unknown> {
|
||||
return this.mapService;
|
||||
}
|
||||
public ExportMap2Png(): string {
|
||||
return this.sceneService.ExportMap2Png();
|
||||
public exportPng(): string {
|
||||
return this.sceneService.exportPng();
|
||||
}
|
||||
|
||||
public get map() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-source",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,8 +24,8 @@
|
|||
"author": "lzxue",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.0.13",
|
||||
"@antv/l7-utils": "^2.0.13",
|
||||
"@antv/l7-core": "^2.0.14",
|
||||
"@antv/l7-utils": "^2.0.14",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/geojson-rewind": "^0.4.0",
|
||||
"@turf/helpers": "^6.1.4",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-utils",
|
||||
"version": "2.0.13",
|
||||
"version": "2.0.14",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,7 +23,11 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@turf/helpers": "^6.1.4"
|
||||
"@turf/helpers": "^6.1.4",
|
||||
"d3-color": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/d3-color": "^1.2.2"
|
||||
},
|
||||
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
|
||||
"publishConfig": {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @ts-ignore
|
||||
import { PointLayer, PolygonLayer, Scale, Scene } from '@antv/l7';
|
||||
import { Layers, PointLayer, PolygonLayer, Scale, Scene } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
|
@ -70,7 +70,16 @@ export default class ScaleComponent extends React.Component {
|
|||
layer.setSelect(e.featureId);
|
||||
});
|
||||
const scaleControl = new Scale();
|
||||
const layers = {
|
||||
点图层: pointLayer,
|
||||
面图层: layer,
|
||||
};
|
||||
const layerControl = new Layers({
|
||||
overlayers: layers,
|
||||
});
|
||||
|
||||
scene.addControl(scaleControl);
|
||||
scene.addControl(layerControl);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class Point3D extends React.Component {
|
|||
center: [120.19382669582967, 30.258134],
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
zoom: 3,
|
||||
zoom: 0,
|
||||
}),
|
||||
});
|
||||
// scene.on('loaded', () => {
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
// code from https://github.com/santilland/plotty/blob/master/src/colorscales.js
|
||||
export const colorScales: {
|
||||
[key: string]: any;
|
||||
} = {
|
||||
rainbow: {
|
||||
colors: [
|
||||
'#96005A',
|
||||
'#0000C8',
|
||||
'#0019FF',
|
||||
'#0098FF',
|
||||
'#2CFF96',
|
||||
'#97FF00',
|
||||
'#FFEA00',
|
||||
'#FF6F00',
|
||||
'#FF0000',
|
||||
],
|
||||
positions: [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1],
|
||||
},
|
||||
jet: {
|
||||
colors: ['#000083', '#003CAA', '#05FFFF', '#FFFF00', '#FA0000', '#800000'],
|
||||
positions: [0, 0.125, 0.375, 0.625, 0.875, 1],
|
||||
},
|
||||
hsv: {
|
||||
colors: [
|
||||
'#ff0000',
|
||||
'#fdff02',
|
||||
'#f7ff02',
|
||||
'#00fc04',
|
||||
'#00fc0a',
|
||||
'#01f9ff',
|
||||
'#0200fd',
|
||||
'#0800fd',
|
||||
'#ff00fb',
|
||||
'#ff00f5',
|
||||
'#ff0006',
|
||||
],
|
||||
positions: [
|
||||
0,
|
||||
0.169,
|
||||
0.173,
|
||||
0.337,
|
||||
0.341,
|
||||
0.506,
|
||||
0.671,
|
||||
0.675,
|
||||
0.839,
|
||||
0.843,
|
||||
1,
|
||||
],
|
||||
},
|
||||
hot: {
|
||||
colors: ['#000000', '#e60000', '#ffd200', '#ffffff'],
|
||||
positions: [0, 0.3, 0.6, 1],
|
||||
},
|
||||
cool: {
|
||||
colors: ['#00ffff', '#ff00ff'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
spring: {
|
||||
colors: ['#ff00ff', '#ffff00'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
summer: {
|
||||
colors: ['#008066', '#ffff66'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
autumn: {
|
||||
colors: ['#ff0000', '#ffff00'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
winter: {
|
||||
colors: ['#0000ff', '#00ff80'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
bone: {
|
||||
colors: ['#000000', '#545474', '#a9c8c8', '#ffffff'],
|
||||
positions: [0, 0.376, 0.753, 1],
|
||||
},
|
||||
copper: {
|
||||
colors: ['#000000', '#ffa066', '#ffc77f'],
|
||||
positions: [0, 0.804, 1],
|
||||
},
|
||||
greys: {
|
||||
colors: ['#000000', '#ffffff'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
yignbu: {
|
||||
colors: [
|
||||
'#081d58',
|
||||
'#253494',
|
||||
'#225ea8',
|
||||
'#1d91c0',
|
||||
'#41b6c4',
|
||||
'#7fcdbb',
|
||||
'#c7e9b4',
|
||||
'#edf8d9',
|
||||
'#ffffd9',
|
||||
],
|
||||
positions: [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1],
|
||||
},
|
||||
greens: {
|
||||
colors: [
|
||||
'#00441b',
|
||||
'#006d2c',
|
||||
'#238b45',
|
||||
'#41ab5d',
|
||||
'#74c476',
|
||||
'#a1d99b',
|
||||
'#c7e9c0',
|
||||
'#e5f5e0',
|
||||
'#f7fcf5',
|
||||
],
|
||||
positions: [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1],
|
||||
},
|
||||
wind: {
|
||||
colors: [
|
||||
'#3288bd',
|
||||
'#66c2a5',
|
||||
'#abdda4',
|
||||
'#e6f598',
|
||||
'#fee08b',
|
||||
'#fdae61',
|
||||
'#f46d43',
|
||||
'#d53e4f',
|
||||
],
|
||||
positions: [0, 0.1, 0.2, 0.6, 0.7, 0.8, 0.9, 1],
|
||||
},
|
||||
yiorrd: {
|
||||
colors: [
|
||||
'#800026',
|
||||
'#bd0026',
|
||||
'#e31a1c',
|
||||
'#fc4e2a',
|
||||
'#fd8d3c',
|
||||
'#feb24c',
|
||||
'#fed976',
|
||||
'#ffeda0',
|
||||
'#ffffcc',
|
||||
],
|
||||
positions: [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1],
|
||||
},
|
||||
bluered: {
|
||||
colors: ['#0000ff', '#ff0000'],
|
||||
positions: [0, 1],
|
||||
},
|
||||
rdbu: {
|
||||
colors: ['#050aac', '#6a89f7', '#bebebe', '#dcaa84', '#e6915a', '#b20a1c'],
|
||||
positions: [0, 0.35, 0.5, 0.6, 0.7, 1],
|
||||
},
|
||||
picnic: {
|
||||
colors: [
|
||||
'#0000ff',
|
||||
'#3399ff',
|
||||
'#66ccff',
|
||||
'#99ccff',
|
||||
'#ccccff',
|
||||
'#ffffff',
|
||||
'#ffccff',
|
||||
'#ff99ff',
|
||||
'#ff66cc',
|
||||
'#ff6666',
|
||||
'#ff0000',
|
||||
],
|
||||
positions: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
|
||||
},
|
||||
portland: {
|
||||
colors: ['#0c3383', '#0a88ba', '#f2d338', '#f28f38', '#d91e1e'],
|
||||
positions: [0, 0.25, 0.5, 0.75, 1],
|
||||
},
|
||||
blackbody: {
|
||||
colors: ['#000000', '#e60000', '#e6d200', '#ffffff', '#a0c8ff'],
|
||||
positions: [0, 0.2, 0.4, 0.7, 1],
|
||||
},
|
||||
earth: {
|
||||
colors: ['#000082', '#00b4b4', '#28d228', '#e6e632', '#784614', '#ffffff'],
|
||||
positions: [0, 0.1, 0.2, 0.4, 0.6, 1],
|
||||
},
|
||||
electric: {
|
||||
colors: ['#000000', '#1e0064', '#780064', '#a05a00', '#e6c800', '#fffadc'],
|
||||
positions: [0, 0.15, 0.4, 0.6, 0.8, 1],
|
||||
},
|
||||
};
|
||||
// export default colorScales;
|
Loading…
Reference in New Issue