diff --git a/dev-demos/features/crs/3857.md b/dev-demos/features/crs/3857.md new file mode 100644 index 0000000000..29fab2366c --- /dev/null +++ b/dev-demos/features/crs/3857.md @@ -0,0 +1,2 @@ +### Leaflet 3857 + \ No newline at end of file diff --git a/dev-demos/features/crs/3857_L7.md b/dev-demos/features/crs/3857_L7.md new file mode 100644 index 0000000000..387245c9ff --- /dev/null +++ b/dev-demos/features/crs/3857_L7.md @@ -0,0 +1,2 @@ +### L7 3857 + \ No newline at end of file diff --git a/dev-demos/features/crs/4326.md b/dev-demos/features/crs/4326.md new file mode 100644 index 0000000000..7477454a09 --- /dev/null +++ b/dev-demos/features/crs/4326.md @@ -0,0 +1,2 @@ +### Leaflet 4326 + \ No newline at end of file diff --git a/dev-demos/features/crs/4326_L7.md b/dev-demos/features/crs/4326_L7.md new file mode 100644 index 0000000000..06a01b467d --- /dev/null +++ b/dev-demos/features/crs/4326_L7.md @@ -0,0 +1,2 @@ +### L7 4326 + \ No newline at end of file diff --git a/dev-demos/features/crs/demos/3857.tsx b/dev-demos/features/crs/demos/3857.tsx new file mode 100644 index 0000000000..1db5ecb233 --- /dev/null +++ b/dev-demos/features/crs/demos/3857.tsx @@ -0,0 +1,44 @@ +import React, { useEffect } from 'react'; +import * as L from 'leaflet'; +import { RDBSource } from 'district-data'; +import 'leaflet/dist/leaflet.css'; + + +export default () => { + useEffect(() => { + const map = L.map('map', { + center: [123, 30], + zoom: 0 + }); + // + + L.tileLayer('http://t{s}.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={z}&TileRow={y}&TileCol={x}&style=default&format=tiles',{ + subdomains:['1','2','3','4','5'], + }).addTo(map); + const source = new RDBSource({}); + source.getData({ level: 'province' }).then((data) => { + const geojson = L.geoJson(data, { + style: { + weight: 2, + opacity: 1, + color: 'white', + dashArray: '3', + fillOpacity: 0.7, + fillColor: '#ff7800', + }, + }).addTo(map); + map.fitBounds(geojson.getBounds()); + }); + + + }, []); + return ( +
+ ); +}; diff --git a/dev-demos/features/crs/demos/3857_L7.tsx b/dev-demos/features/crs/demos/3857_L7.tsx new file mode 100644 index 0000000000..64ef5d5c42 --- /dev/null +++ b/dev-demos/features/crs/demos/3857_L7.tsx @@ -0,0 +1,70 @@ +// @ts-ignore +import { Scene, RasterLayer,PolygonLayer } from '@antv/l7'; +import { RDBSource } from 'district-data'; +// @ts-ignore +import { Map } from '@antv/l7-maps'; +import React, { useEffect } from 'react'; + +export default () => { + useEffect(() => { + const scene = new Scene({ + id: 'map', + map: new Map({ + center: [123, 30], + zoom: 1, + crs:'EPSG:3857' + }), + }); + + const url = + 'http://t0.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={z}&TileRow={y}&TileCol={x}&style=default&format=tiles'; + + + + scene.on('loaded', () => { + const source = new RDBSource({}); + const layer = new RasterLayer({ + zIndex: 1, + }).source(url, { + parser: { + type: 'rasterTile', + tileSize: 256, + }, + }); + source.getData({ level: 'province' }).then((data) => { + const fill = new PolygonLayer({ + autoFit: true, + zIndex: 2, + }) + .source(data) + .shape('fill') + .color('name', [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + '#ffff99', + '#b15928', + ]) + .active(false); + scene.addLayer(fill); + scene.addLayer(layer); + }); + }); + }, []); + return ( +
+ ); +}; diff --git a/dev-demos/features/crs/demos/4326.tsx b/dev-demos/features/crs/demos/4326.tsx new file mode 100644 index 0000000000..7387491d01 --- /dev/null +++ b/dev-demos/features/crs/demos/4326.tsx @@ -0,0 +1,47 @@ +import React, { useEffect } from 'react'; +import * as L from 'leaflet'; +import { RDBSource } from 'district-data'; +import 'leaflet/dist/leaflet.css'; + + +export default () => { + useEffect(() => { + const map = L.map('map', { + crs: L.CRS.EPSG4326, + center: [123, 30], + zoom: 0 + }); + // + + + L.tileLayer('http://t{s}.tianditu.gov.cn/img_c/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix={z}&TileRow={y}&TileCol={x}&style=default&format=tiles',{ + subdomains:['1','2','3','4','5'], + zoomOffset:1, + }).addTo(map); + const source = new RDBSource({}); + source.getData({ level: 'province' }).then((data) => { + const geojson = L.geoJson(data, { + style: { + weight: 2, + opacity: 1, + color: 'white', + dashArray: '3', + fillOpacity: 0.7, + fillColor: '#ff7800', + }, + }).addTo(map); + // map.fitBounds(geojson.getBounds()); + }); + + + }, []); + return ( +
+ ); +}; diff --git a/dev-demos/features/crs/demos/4326_L7.tsx b/dev-demos/features/crs/demos/4326_L7.tsx new file mode 100644 index 0000000000..f46e890f7d --- /dev/null +++ b/dev-demos/features/crs/demos/4326_L7.tsx @@ -0,0 +1,70 @@ +// @ts-ignore +import { Scene, RasterLayer,PolygonLayer } from '@antv/l7'; +// @ts-ignore +import { Map } from '@antv/l7-maps'; +import React, { useEffect } from 'react'; +import { RDBSource } from 'district-data'; + +export default () => { + useEffect(() => { + const scene = new Scene({ + id: 'map', + map: new Map({ + center: [123, 30], + zoom: 0, + crs:'EPSG:4326' + }), + }); + + const url = + 'http://t0.tianditu.gov.cn/img_c/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=c&TileMatrix={z}&TileRow={y}&TileCol={x}&style=default&format=tiles'; + + const layer = new RasterLayer({ + zIndex: 1, + }).source(url, { + parser: { + type: 'rasterTile', + tileSize: 256, + zoomOffset: 0, + }, + }); + + scene.on('loaded', () => { + const source = new RDBSource({}); + source.getData({ level: 'province' }).then((data) => { + const fill = new PolygonLayer({ + autoFit: true, + zIndex: 2, + }) + .source(data) + .shape('fill') + .color('name', [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + '#ffff99', + '#b15928', + ]) + .active(false); + scene.addLayer(fill); + // scene.addLayer(layer); + }); + }); + }, []); + return ( +
+ ); +}; diff --git a/dev-demos/tile/Mask/demos/vector_raster.tsx b/dev-demos/tile/Mask/demos/vector_raster.tsx new file mode 100644 index 0000000000..212b143687 --- /dev/null +++ b/dev-demos/tile/Mask/demos/vector_raster.tsx @@ -0,0 +1,84 @@ +// @ts-ignore +import { Scene, RasterLayer, MaskLayer,Source,PolygonLayer } from '@antv/l7'; +// @ts-ignore +import { Map } from '@antv/l7-maps'; +import React, { useEffect } from 'react'; + +export default () => { + useEffect(() => { + const scene = new Scene({ + id: 'map', + + map: new Map({ + center: [116.39852, 39.918255], + zoom: 9, + }), + }); + + const source = new Source( + 'https://gridwise.alibaba-inc.com/tile/test?z={z}&x={x}&y={y}', + { + parser: { + type: 'mvt', + tileSize: 256, + }, + }, + ); + + const fillLayer = new PolygonLayer({ + featureId: 'space_id', + zIndex: 3, + visible: false, + sourceLayer: 'default', // woods hillshade contour ecoregions ecoregions2 city + }) + .source(source) + .shape('fill') + .scale('space_val', { + type: 'quantize', + domain: [0, 100], + }) + .color('space_val', [ + '#f2f0f7', + '#cbc9e2', + '#9e9ac8', + '#756bb1', + '#54278f', + ]) + .style({ + opacity: 0.1, + }); + + + + const layer = new RasterLayer({ + zIndex: 2, + maskLayers:[fillLayer], + enableMask: true, + }).source( + 'https://tiles{1-3}.geovisearth.com/base/v1/img/{z}/{x}/{y}?format=webp&tmsIds=w&token=b2a0cfc132cd60b61391b9dd63c15711eadb9b38a9943e3f98160d5710aef788', + { + parser: { + type: 'rasterTile', + tileSize: 256, + }, + }, + ).style({ + opacity:1 + }); + + scene.on('loaded', () => { + + scene.addLayer(layer); + scene.addLayer(fillLayer); + }); + }, []); + return ( +
+ ); +}; diff --git a/dev-demos/tile/Mask/vector_raster.md b/dev-demos/tile/Mask/vector_raster.md new file mode 100644 index 0000000000..7515e8733e --- /dev/null +++ b/dev-demos/tile/Mask/vector_raster.md @@ -0,0 +1,8 @@ +--- +group: + path: 'Mask' + title: 掩膜 +title: 矢量栅格瓦片 +order: 2 +--- + \ No newline at end of file diff --git a/dev-demos/tile/Vector/demos/citytile.tsx b/dev-demos/tile/Vector/demos/citytile.tsx index 8580ac435b..d86e2277ce 100644 --- a/dev-demos/tile/Vector/demos/citytile.tsx +++ b/dev-demos/tile/Vector/demos/citytile.tsx @@ -2,9 +2,15 @@ import { Scene, Source, PolygonLayer, LineLayer } from '@antv/l7'; // @ts-ignore import { GaodeMap } from '@antv/l7-maps'; -import React, { useEffect } from 'react'; +import React, { useEffect,useState } from 'react'; export default () => { + const [tileSource, setTileSource] = useState(); + const onReload = ()=>{ + tileSource.reloadAllTile(); + // tileSource.reloadTilebyId(9,421,193) + // tileSource +} useEffect(() => { const scene = new Scene({ id: 'map', @@ -32,6 +38,7 @@ export default () => { }, ); + setTileSource(source) const layer = new PolygonLayer({ featureId: 'space_id', @@ -79,6 +86,8 @@ export default () => { }); }, []); return ( + <> +
{ position: 'relative', }} /> + ); }; diff --git a/dev-demos/tile/Vector/demos/vectormask.tsx b/dev-demos/tile/Vector/demos/vectormask.tsx index 2b418a3377..a176c72468 100644 --- a/dev-demos/tile/Vector/demos/vectormask.tsx +++ b/dev-demos/tile/Vector/demos/vectormask.tsx @@ -27,7 +27,6 @@ import { 'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.webp?sku=101ifSAcKcVFs&access_token=pk.eyJ1IjoidW5mb2xkZWRpbmMiLCJhIjoiY2s5ZG90MjMzMDV6eDNkbnh2cDJvbHl4NyJ9.BT2LAvHi31vNNEplsgxucQ'; const layer1 = new RasterLayer({ zIndex: 1, - mask: true, }).source(url1, { parser: { type: 'rasterTile', @@ -44,11 +43,7 @@ import { }, }, ); - - const mask2 = new MaskLayer({ - sourceLayer: 'state_s10_27', // woods hillshade contour ecoregions ecoregions2 city - }).source(source); - + const layer = new LineLayer({ featureId: 'id', zIndex: 3, @@ -91,7 +86,6 @@ import { scene.on('loaded', () => { - scene.addLayer(mask2); scene.addLayer(layer1); scene.addLayer(layer); diff --git a/package.json b/package.json index 8eb5e80b78..0aa23c08f8 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "jest-less-loader": "^0.1.2", "jest-styled-components": "^6.2.1", "jsencrypt": "^3.2.1", - "leaflet": "^1.8.0", + "leaflet": "^1.9.3", "lerc": "^3.0.0", "lerna": "^3.16.4", "less": "^4.1.3", @@ -231,5 +231,6 @@ "tnpm": { "mode": "yarn" }, - "version": "0.0.0" + "version": "0.0.0", + "dependencies": {} } diff --git a/packages/component/src/control/geoLocate.ts b/packages/component/src/control/geoLocate.ts index 1f90c179f4..3e60da17c6 100644 --- a/packages/component/src/control/geoLocate.ts +++ b/packages/component/src/control/geoLocate.ts @@ -1,4 +1,4 @@ -import { Point } from '@antv/l7-core'; +import { IPointArray } from '@antv/l7-core'; import { isNaN } from 'lodash'; import { createL7Icon } from '../utils/icon'; import ButtonControl, { @@ -6,7 +6,7 @@ import ButtonControl, { } from './baseControl/buttonControl'; export interface IGeoLocateOption extends IButtonControlOption { - transform: (position: Point) => Point | Promise; + transform: (position: IPointArray) => IPointArray | Promise; } export { GeoLocate }; @@ -38,7 +38,7 @@ export default class GeoLocate extends ButtonControl { * 通过浏览器 API 获取当前所在经纬度 */ public getGeoLocation = () => { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { window.navigator.geolocation.getCurrentPosition( ({ coords }) => { const { longitude, latitude } = coords ?? {}; diff --git a/packages/component/src/marker-layer.ts b/packages/component/src/marker-layer.ts index fa553cfdb8..d511f1e451 100644 --- a/packages/component/src/marker-layer.ts +++ b/packages/component/src/marker-layer.ts @@ -1,4 +1,5 @@ import { + IBoundsArray, IMapService, IMarker, IMarkerContainerAndBounds, @@ -8,7 +9,6 @@ import { bindAll, boundsContains, DOM, - IBounds, padBounds, Satistics, } from '@antv/l7-utils'; @@ -37,7 +37,7 @@ export default class MarkerLayer extends EventEmitter { private mapsService: IMapService; private scene: Container; private zoom: number; - private bbox: IBounds; + private bbox: IBoundsArray; private inited: boolean; private containerSize: IMarkerContainerAndBounds; @@ -229,7 +229,7 @@ export default class MarkerLayer extends EventEmitter { this.clusterIndex.load(this.points); } - private getClusterMarker(viewBounds: IBounds, zoom: number) { + private getClusterMarker(viewBounds: IBoundsArray, zoom: number) { const viewBBox = viewBounds[0].concat(viewBounds[1]); const clusterPoint = this.clusterIndex.getClusters(viewBBox, zoom); this.clusterMarkers.forEach((marker: IMarker) => { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6662f659bd..ef42271c92 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -23,6 +23,8 @@ export * from './services/interaction/IPickingService'; /** 暴露服务接口供其他 packages 实现 */ export * from './services/layer/ILayerService'; export * from './services/layer/IStyleAttributeService'; +export * from './services/map/geo'; +export * from './services/map/ICRS'; export * from './services/map/IMapService'; export * from './services/renderer/gl'; /** 全部渲染服务接口 */ diff --git a/packages/core/src/services/component/IMarkerService.ts b/packages/core/src/services/component/IMarkerService.ts index b426bdbf33..e6693fde5d 100644 --- a/packages/core/src/services/component/IMarkerService.ts +++ b/packages/core/src/services/component/IMarkerService.ts @@ -1,6 +1,7 @@ -import { anchorType, IBounds } from '@antv/l7-utils'; +import { anchorType } from '@antv/l7-utils'; import { Container } from 'inversify'; -import { ILngLat, IMapService, IPoint } from '../map/IMapService'; +import { IBoundsArray, ILngLat, IPoint } from '../map/geo'; +import { IMapService } from '../map/IMapService'; import { IPopup } from './IPopupService'; export interface IMarkerScene { getMapService(): IMapService; @@ -23,7 +24,7 @@ export interface IMarkerOption { export interface IMarkerContainerAndBounds { containerWidth: number; containerHeight: number; - bounds: IBounds; + bounds: IBoundsArray; } export interface IMarker { diff --git a/packages/core/src/services/component/IPopupService.ts b/packages/core/src/services/component/IPopupService.ts index 340c8999bc..d4187bf93c 100644 --- a/packages/core/src/services/component/IPopupService.ts +++ b/packages/core/src/services/component/IPopupService.ts @@ -1,7 +1,7 @@ import { anchorType, DOM } from '@antv/l7-utils'; import EventEmitter from 'eventemitter3'; import { Container } from 'inversify'; -import { ILngLat } from '../map/IMapService'; +import { ILngLat } from '../map/geo'; export interface IPopupOption { /** diff --git a/packages/core/src/services/interaction/IInteractionService.ts b/packages/core/src/services/interaction/IInteractionService.ts index 21c95324f1..fdbb227986 100644 --- a/packages/core/src/services/interaction/IInteractionService.ts +++ b/packages/core/src/services/interaction/IInteractionService.ts @@ -1,4 +1,4 @@ -import { ILngLat } from '../map/IMapService'; +import { ILngLat } from '../map/geo'; export enum InteractionEvent { Hover = 'hover', Click = 'click', diff --git a/packages/core/src/services/interaction/IPickingService.ts b/packages/core/src/services/interaction/IPickingService.ts index 09b8b62504..feb940ccbb 100644 --- a/packages/core/src/services/interaction/IPickingService.ts +++ b/packages/core/src/services/interaction/IPickingService.ts @@ -1,6 +1,6 @@ import { IInteractionTarget } from '../interaction/IInteractionService'; import { ILayer } from '../layer/ILayerService'; -import { ILngLat } from '../map/IMapService'; +import { ILngLat } from '../map/geo'; export interface IPickingService { pickedColors: Uint8Array | undefined; pickedTileLayers: ILayer[]; diff --git a/packages/core/src/services/interaction/InteractionService.ts b/packages/core/src/services/interaction/InteractionService.ts index cb52841a9e..a460bdaf20 100644 --- a/packages/core/src/services/interaction/InteractionService.ts +++ b/packages/core/src/services/interaction/InteractionService.ts @@ -5,7 +5,8 @@ import Hammer from 'l7hammerjs'; import 'reflect-metadata'; // @ts-ignore import { TYPES } from '../../types'; -import { ILngLat, IMapService } from '../map/IMapService'; +import { ILngLat } from '../map/geo'; +import { IMapService } from '../map/IMapService'; import { IInteractionService, InteractionEvent } from './IInteractionService'; const DragEventMap: { [key: string]: string } = { panstart: 'dragstart', diff --git a/packages/core/src/services/interaction/PickingService.ts b/packages/core/src/services/interaction/PickingService.ts index 7b3cb2451f..7020f54634 100644 --- a/packages/core/src/services/interaction/PickingService.ts +++ b/packages/core/src/services/interaction/PickingService.ts @@ -10,7 +10,8 @@ import { InteractionEvent, } from '../interaction/IInteractionService'; import { ILayer, ILayerService } from '../layer/ILayerService'; -import { ILngLat, IMapService } from '../map/IMapService'; +import { ILngLat } from '../map/geo'; +import { IMapService } from '../map/IMapService'; import { gl } from '../renderer/gl'; import { IFramebuffer } from '../renderer/IFramebuffer'; import { IRendererService } from '../renderer/IRendererService'; diff --git a/packages/core/src/services/map/ICRS.ts b/packages/core/src/services/map/ICRS.ts new file mode 100644 index 0000000000..bae05a0eca --- /dev/null +++ b/packages/core/src/services/map/ICRS.ts @@ -0,0 +1,29 @@ +import { + Bounds, + ILngLat, + IPoint, + IProjection, + LngLat, + LngLatBounds, + LngLatLike, + Point, + Transformation, +} from './geo'; +export type TypeCRS = 'EPSG:3857' | 'EPSG:4326' | 'Earth' | undefined; +export interface ICRS { + code: TypeCRS; + transformation: Transformation; + projection: IProjection; + wrapLng: [number, number]; + wrapLat: [number, number]; + infinite: boolean; + lngLatToPoint(lngLat: LngLatLike, zoom: number): Point; + pointToLngLat(point: IPoint, zoom: number): LngLat; + project(lngLat: ILngLat): Point; + unproject(point: IPoint): LngLat; + scale(zoom: number): number; + zoom(scale: number): number; + getProjectedBounds(zoom: number): Bounds | null; + wrapLnglat(lngLat: LngLat): LngLat; + wrapLnglatBounds(lngLatBounds: LngLatBounds): LngLatBounds; +} diff --git a/packages/core/src/services/map/IMapService.ts b/packages/core/src/services/map/IMapService.ts index e7d7ce84d2..2af410be71 100644 --- a/packages/core/src/services/map/IMapService.ts +++ b/packages/core/src/services/map/IMapService.ts @@ -1,20 +1,15 @@ import { Container } from 'inversify'; import { IViewport } from '../camera/ICameraService'; -export type Point = [number, number]; -export type Bounds = [[number, number], [number, number]]; -export interface ILngLat { - lng: number; - lat: number; -} -export interface IPoint { - x: number; - y: number; -} -export interface IMercator { - x: number; - y: number; - z: number; -} +import { + IBoundsArray, + ILngLat, + IMercator, + IPoint, + IPointArray, + LngLatArray, +} from './geo'; +import { ICRS } from './ICRS'; + export interface IStatusOptions { showIndoorMap: boolean; resizeEnable: boolean; @@ -71,6 +66,8 @@ export interface IMapService { once(type: string, handler: (...args: any[]) => void): void; // get dom getContainer(): HTMLElement | null; + // 获取地图投影; + getCrs?(): ICRS; getSize(): [number, number]; // get map status method getMinZoom(): number; @@ -81,7 +78,7 @@ export interface IMapService { getCenter(option?: ICameraOptions): ILngLat; getPitch(): number; getRotation(): number; - getBounds(): Bounds; + getBounds(): IBoundsArray; getMapContainer(): HTMLElement | null; getMapCanvasContainer(): HTMLElement; getMapStyleConfig(): MapStyleConfig; // 获取当前地图类型默认的样式配置 @@ -93,10 +90,10 @@ export interface IMapService { setRotation(rotation: number): void; zoomIn(option?: any, eventData?: any): void; zoomOut(option?: any, eventData?: any): void; - panTo(p: Point): void; + panTo(p: IPointArray): void; panBy(x: number, y: number): void; - fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void; - setZoomAndCenter(zoom: number, center: Point): void; + fitBounds(bound: IBoundsArray, fitBoundsOptions?: unknown): void; + setZoomAndCenter(zoom: number, center: IPointArray): void; setCenter(center: [number, number], option?: ICameraOptions): void; setPitch(pitch: number): void; setZoom(zoom: number): void; @@ -105,11 +102,11 @@ export interface IMapService { // coordinates methods meterToCoord(center: number[], lnglat: number[]): number; - pixelToLngLat(pixel: Point): ILngLat; - lngLatToPixel(lnglat: Point): IPoint; - containerToLngLat(pixel: Point): ILngLat; - lngLatToContainer(lnglat: Point): IPoint; - lngLatToMercator(lnglat: [number, number], altitude: number): IMercator; + pixelToLngLat(pixel: LngLatArray): ILngLat; + lngLatToPixel(lnglat: LngLatArray): IPoint; + containerToLngLat(pixel: IPointArray): ILngLat; + lngLatToContainer(lnglat: LngLatArray): IPoint; + lngLatToMercator(lnglat: LngLatArray, altitude: number): IMercator; getModelMatrix( lnglat: [number, number], altitude: number, @@ -164,7 +161,7 @@ export interface IEarthService { getCenter(option?: ICameraOptions): ILngLat; getPitch(): number; getRotation(): number; - getBounds(): Bounds; + getBounds(): IBoundsArray; getMapContainer(): HTMLElement | null; getMapCanvasContainer(): HTMLElement; getMapStyleConfig(): MapStyleConfig; @@ -173,10 +170,10 @@ export interface IEarthService { setRotation(rotation: number): void; zoomIn(option?: any, eventData?: any): void; zoomOut(option?: any, eventData?: any): void; - panTo(p: Point): void; + panTo(p: IPointArray): void; panBy(x: number, y: number): void; - fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void; - setZoomAndCenter(zoom: number, center: Point): void; + fitBounds(bound: IBoundsArray, fitBoundsOptions?: unknown): void; + setZoomAndCenter(zoom: number, center: IPointArray): void; setCenter(center: [number, number], option?: ICameraOptions): void; setPitch(pitch: number): void; setZoom(zoom: number): void; @@ -185,10 +182,10 @@ export interface IEarthService { // coordinates methods meterToCoord(center: number[], lnglat: number[]): number; - pixelToLngLat(pixel: Point): ILngLat; - lngLatToPixel(lnglat: Point): IPoint; - containerToLngLat(pixel: Point): ILngLat; - lngLatToContainer(lnglat: Point): IPoint; + pixelToLngLat(pixel: IPointArray): ILngLat; + lngLatToPixel(lnglat: IPointArray): IPoint; + containerToLngLat(pixel: IPointArray): ILngLat; + lngLatToContainer(lnglat: LngLatArray): IPoint; lngLatToMercator(lnglat: [number, number], altitude: number): IMercator; getModelMatrix( lnglat: [number, number], diff --git a/packages/core/src/services/map/geo/bounds.ts b/packages/core/src/services/map/geo/bounds.ts new file mode 100644 index 0000000000..a2e793e8ec --- /dev/null +++ b/packages/core/src/services/map/geo/bounds.ts @@ -0,0 +1,167 @@ +import { Point, PointLike } from './point'; + +export type IBoundsArray = [[number, number], [number, number]]; +export type IBoundsLike = + | Bounds + | [PointLike, PointLike] + | [number, number, number, number]; +export class Bounds { + public min: Point; + public max: Point; + + public static convert(input: IBoundsLike | PointLike): Bounds { + if (input instanceof Bounds) { + return input; + } + return new Bounds(input); + } + + constructor(a: PointLike | IBoundsLike, b?: PointLike) { + if (!a) { + return; + } + const points = b ? [a, b] : a; + if (Array.isArray(points) && typeof points[0] === 'number') { + this.extend( + points as [number, number] | [number, number, number, number], + ); + } else if (Array.isArray(points)) { + for (let i = 0, len = points.length; i < len; i++) { + if (typeof points[i] !== 'number') { + // @ts-ignore + this.extend(points[i]); + } + } + } + } + + public extend(obj: PointLike | IBoundsLike): Bounds { + const min = this.min; + const max = this.max; + let min2: Point = new Point(0, 0); + let max2: Point = new Point(0, 0); + // 点 + if ( + obj instanceof Point || + (Array.isArray(obj) && obj.length === 2 && typeof obj[0] === 'number') + ) { + min2 = Point.convert(obj); + max2 = Point.convert(obj); + } else if (obj instanceof Bounds) { + min2 = obj.min; + max2 = obj.max; + if (!min2 || !max2) { + return this; + } + } else { + if (Array.isArray(obj)) { + min2 = Point.convert([obj[0], obj[1]]); + max2 = Point.convert([obj[2], obj[3]]); + } + } + + if (!min && !max) { + this.min = min2.clone(); + this.max = max2.clone(); + } else { + this.min.x = Math.min(min2.x, this.min.x); + this.max.x = Math.max(max2.x, this.max.x); + this.min.y = Math.min(min2.y, this.min.y); + this.max.y = Math.max(max2.y, this.max.y); + } + return this; + } + + public getCenter(): Point { + return Point.convert(this.min.add(this.max).div(2)); + } + public getBottomLeft(): Point { + return Point.convert([this.min.x, this.max.y]); + } + public getTopRight(): Point { + return Point.convert([this.max.x, this.min.y]); + } + public getTopLeft(): Point { + return Point.convert(this.min); + } + public getBottomRight(): Point { + return Point.convert(this.max); + } + public getSize(): Point { + return this.max.sub(this.min); + } + public contains(a: PointLike | IBoundsLike): boolean { + let obj = a; + let min: Point; + let max: Point; + // Point 为点 + (Array.isArray(obj) && obj.length === 2 && typeof obj[0] === 'number') || + obj instanceof Point + ? (obj = Point.convert(obj)) + : (obj = Bounds.convert(obj)); + + if (obj instanceof Bounds) { + min = obj.min; + max = obj.max; + } else { + min = max = obj as Point; + } + + return ( + min.x >= this.min.x && + max.x <= this.max.x && + min.y >= this.min.y && + max.y <= this.max.y + ); + } + public intersects(bounds: IBoundsLike): boolean { + bounds = Bounds.convert(bounds); + + const min = this.min; + const max = this.max; + const min2 = bounds.min; + const max2 = bounds.max; + const xIntersects = max2.x >= min.x && min2.x <= max.x; + const yIntersects = max2.y >= min.y && min2.y <= max.y; + + return xIntersects && yIntersects; + } + public overlaps(bounds: IBoundsLike): boolean { + bounds = Bounds.convert(bounds); + + const min = this.min; + const max = this.max; + const min2 = bounds.min; + const max2 = bounds.max; + const xOverlaps = max2.x > min.x && min2.x < max.x; + const yOverlaps = max2.y > min.y && min2.y < max.y; + + return xOverlaps && yOverlaps; + } + public isValid(): boolean { + return !!(this.min && this.max); + } + public pad(bufferRatio: number): Bounds { + const min = this.min; + const max = this.max; + const heightBuffer = Math.abs(min.x - max.x) * bufferRatio; + const widthBuffer = Math.abs(min.y - max.y) * bufferRatio; + + return Bounds.convert([ + Point.convert([min.x - heightBuffer, min.y - widthBuffer]), + Point.convert([max.x + heightBuffer, max.y + widthBuffer]), + ]); + } + public equals(bounds: Bounds): boolean { + if (!bounds) { + return false; + } + + bounds = Bounds.convert(bounds); + + return ( + this.min.equals(bounds.getTopLeft()) && + this.max.equals(bounds.getBottomRight()) + ); + } +} diff --git a/packages/core/src/services/map/geo/index.ts b/packages/core/src/services/map/geo/index.ts new file mode 100644 index 0000000000..82b0f0b877 --- /dev/null +++ b/packages/core/src/services/map/geo/index.ts @@ -0,0 +1,7 @@ +export * from './bounds'; +export * from './lng_lat'; +export * from './lng_lat_bounds'; +export * from './mercator'; +export * from './point'; +export * from './projection'; +export * from './transformation'; diff --git a/packages/map/src/geo/lng_lat.ts b/packages/core/src/services/map/geo/lng_lat.ts similarity index 90% rename from packages/map/src/geo/lng_lat.ts rename to packages/core/src/services/map/geo/lng_lat.ts index d88be31376..8efb9fdc38 100644 --- a/packages/map/src/geo/lng_lat.ts +++ b/packages/core/src/services/map/geo/lng_lat.ts @@ -1,12 +1,15 @@ -import { wrap } from '../util'; +import { wrap } from '@antv/l7-utils'; + export const earthRadius = 6371008.8; -export type LngLatLike = - | LngLat - | { lng: number; lat: number } - | { lon: number; lat: number } - | [number, number]; +export interface ILngLat { + lng: number; + lat: number; +} +export type LngLatArray = [number, number]; + +export type LngLatLike = ILngLat | { lon: number; lat: number } | LngLatArray; -export default class LngLat { +export class LngLat { public static convert(input: LngLatLike): LngLat { if (input instanceof LngLat) { return input; diff --git a/packages/map/src/geo/lng_lat_bounds.ts b/packages/core/src/services/map/geo/lng_lat_bounds.ts similarity index 97% rename from packages/map/src/geo/lng_lat_bounds.ts rename to packages/core/src/services/map/geo/lng_lat_bounds.ts index 7a2a0c2e6f..257a46918d 100644 --- a/packages/map/src/geo/lng_lat_bounds.ts +++ b/packages/core/src/services/map/geo/lng_lat_bounds.ts @@ -1,9 +1,10 @@ -import LngLat, { LngLatLike } from './lng_lat'; +import { LngLat, LngLatLike } from './lng_lat'; export type LngLatBoundsLike = | LngLatBounds | [LngLatLike, LngLatLike] | [number, number, number, number]; -export default class LngLatBounds { + +export class LngLatBounds { public static convert(input: LngLatBoundsLike): LngLatBounds { if (input instanceof LngLatBounds) { return input; diff --git a/packages/map/src/geo/mercator.ts b/packages/core/src/services/map/geo/mercator.ts similarity index 94% rename from packages/map/src/geo/mercator.ts rename to packages/core/src/services/map/geo/mercator.ts index 4504e4c9e0..838ba4c3da 100644 --- a/packages/map/src/geo/mercator.ts +++ b/packages/core/src/services/map/geo/mercator.ts @@ -1,5 +1,9 @@ -import LngLat, { earthRadius, LngLatLike } from '../geo/lng_lat'; - +import { earthRadius, LngLat, LngLatLike } from './lng_lat'; +export interface IMercator { + x: number; + y: number; + z: number; +} /* * The average circumference of the world in meters. */ diff --git a/packages/map/src/geo/point.ts b/packages/core/src/services/map/geo/point.ts similarity index 95% rename from packages/map/src/geo/point.ts rename to packages/core/src/services/map/geo/point.ts index d3a9e8565c..60e972772a 100644 --- a/packages/map/src/geo/point.ts +++ b/packages/core/src/services/map/geo/point.ts @@ -1,6 +1,13 @@ -export type PointLike = [number, number] | Point; +export interface IPoint { + x: number; + y: number; +} + +export type IPointArray = [number, number]; + +export type PointLike = IPointArray | Point | IPoint; -export default class Point { +export class Point { public static convert(a: any) { if (a instanceof Point) { return a; diff --git a/packages/core/src/services/map/geo/projection.ts b/packages/core/src/services/map/geo/projection.ts new file mode 100644 index 0000000000..41f520daf5 --- /dev/null +++ b/packages/core/src/services/map/geo/projection.ts @@ -0,0 +1,7 @@ +import { LngLat, LngLatLike } from './lng_lat'; +import { IPoint, Point } from './point'; +export interface IProjection { + bounds: any; + project(lngLat: LngLatLike): Point; + unproject(point: IPoint): LngLat; +} diff --git a/packages/core/src/services/map/geo/transformation.ts b/packages/core/src/services/map/geo/transformation.ts new file mode 100644 index 0000000000..dfd1a159c9 --- /dev/null +++ b/packages/core/src/services/map/geo/transformation.ts @@ -0,0 +1,39 @@ +import { IPoint, Point } from './point'; +export class Transformation { + private a: number = 0; + private b: number = 0; + private c: number = 0; + private d: number = 0; + + constructor( + a: number | [number, number, number, number], + b: number, + c: number, + d: number, + ) { + if (Array.isArray(a)) { + this.a = a[0]; + this.b = a[1]; + this.c = a[2]; + this.d = a[3]; + return; + } + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + public transform(point: IPoint, scale: number = 1) { + point.x = scale * (this.a * point.x + this.b); + point.y = scale * (this.c * point.y + this.d); + return new Point(point.x, point.y); + } + + public untransform(point: IPoint, scale: number = 1) { + return new Point( + (point.x / scale - this.b) / this.a, + (point.y / scale - this.d) / this.c, + ); + } +} diff --git a/packages/core/src/services/renderer/passes/PixelPickingPass.ts b/packages/core/src/services/renderer/passes/PixelPickingPass.ts index 3927f61c45..6113c9b294 100644 --- a/packages/core/src/services/renderer/passes/PixelPickingPass.ts +++ b/packages/core/src/services/renderer/passes/PixelPickingPass.ts @@ -6,7 +6,7 @@ import { InteractionEvent, } from '../../interaction/IInteractionService'; import { ILayer } from '../../layer/ILayerService'; -import { ILngLat } from '../../map/IMapService'; +import { ILngLat } from '../../map/geo'; import { gl } from '../gl'; import { IFramebuffer } from '../IFramebuffer'; import { PassType } from '../IMultiPassRenderer'; diff --git a/packages/core/src/services/source/ISourceService.ts b/packages/core/src/services/source/ISourceService.ts index 8de0000d34..8e9eb33971 100644 --- a/packages/core/src/services/source/ISourceService.ts +++ b/packages/core/src/services/source/ISourceService.ts @@ -1,5 +1,7 @@ import { RequestParameters, TilesetManager } from '@antv/l7-utils'; import { BBox } from '@turf/helpers'; +import { ICRS } from '../map/ICRS'; + export type DataType = string | object[] | object; export type SourceEventType = 'inited' | 'sourceUpdate' | 'update'; // 栅格瓦片解析配置项 @@ -95,6 +97,7 @@ export interface ISourceCFG { autoRender?: boolean; parser?: IParserCfg | ITileParserCFG; transforms?: ITransform[]; + crs?: ICRS | undefined; } export interface IClusterOptions { enable: false; @@ -143,6 +146,7 @@ export interface ISource { clusterOptions: Partial; extent: BBox; tileset: TilesetManager | undefined; + setCRS(crs: ICRS): void; getSourceCfg(): any; setData(data: any, options?: ISourceCFG): void; updateClusterData(zoom: number): void; @@ -150,6 +154,11 @@ export interface ISource { getFeatureId(field: string, value: any): number | undefined; getParserType(): string; getClusters(zoom: number): any; + // 瓦片图层 + reloadAllTile(): void; + reloadTilebyId(z: number, x: number, y: number): void; + reloadTileByLnglat(lng: number, lat: number, z: number): void; + reloadTileByExtent(bounds: [number, number, number, number], z: number): void; getClustersLeaves(id: number): any; updateFeaturePropertiesById( id: number, diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index abe0292d65..c37c33b301 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -1110,6 +1110,10 @@ export default class BaseLayer if (this.layerSource) { this.layerSource.off('update', this.sourceEvent); } + // TODO: mapservice 未初始化如何设置 CRS; + // if (this.mapService.getCrs) { + // source.setCRS(this.mapService.getCrs()); + // } this.layerSource = source; this.clusterZoom = 0; diff --git a/packages/layers/src/wind/models/wind.ts b/packages/layers/src/wind/models/wind.ts index e9d7f90a16..8c09a1da5a 100644 --- a/packages/layers/src/wind/models/wind.ts +++ b/packages/layers/src/wind/models/wind.ts @@ -4,9 +4,9 @@ import { IEncodeFeature, IModel, IModelUniform, + IPointArray, IRenderOptions, ITexture2D, - Point, } from '@antv/l7-core'; import { FrequencyController } from '@antv/l7-utils'; import BaseModel from '../../core/BaseModel'; @@ -31,7 +31,7 @@ export default class WindModel extends BaseModel { protected texture: ITexture2D; private colorModel: IModel; private wind: IWind; - private imageCoords: [Point, Point]; + private imageCoords: [IPointArray, IPointArray]; private sizeScale: number = 0.5; // https://mapbox.github.io/webgl-wind/demo/ // source: 'http://nomads.ncep.noaa.gov', @@ -74,7 +74,10 @@ export default class WindModel extends BaseModel { this.cacheZoom = Math.floor(this.mapService.getZoom()); const glContext = this.rendererService.getGLContext(); - this.imageCoords = source.data?.dataArray[0].coordinates as [Point, Point]; + this.imageCoords = source.data?.dataArray[0].coordinates as [ + IPointArray, + IPointArray, + ]; source.data?.images?.then((imageData: HTMLImageElement[]) => { this.sizeScale = sizeScale * this.getZoomScale(); diff --git a/packages/map/package.json b/packages/map/package.json index 3f0f3d78cd..a6ac3adc13 100644 --- a/packages/map/package.json +++ b/packages/map/package.json @@ -41,6 +41,7 @@ "homepage": "https://github.com/antvis/L7#readme", "dependencies": { "@antv/l7-utils": "2.15.3", + "@antv/l7-core": "2.15.3", "@babel/runtime": "^7.7.7", "@mapbox/point-geometry": "^0.1.0", "@mapbox/unitbezier": "^0.0.0", diff --git a/packages/map/src/camera.ts b/packages/map/src/camera.ts index a572b86433..e7f41360ba 100644 --- a/packages/map/src/camera.ts +++ b/packages/map/src/camera.ts @@ -1,10 +1,16 @@ // @ts-ignore +import { + ICRS, + LngLat, + LngLatBounds, + LngLatBoundsLike, + LngLatLike, + Point, + PointLike, +} from '@antv/l7-core'; import { EventEmitter } from 'eventemitter3'; import { merge } from 'lodash'; import { IPaddingOptions } from './geo/edge_insets'; -import LngLat, { LngLatLike } from './geo/lng_lat'; -import LngLatBounds, { LngLatBoundsLike } from './geo/lng_lat_bounds'; -import Point, { PointLike } from './geo/point'; import Transform from './geo/transform'; import { Event } from './handler/events/event'; import { IMapOptions } from './interface'; @@ -65,7 +71,8 @@ export default class Camera extends EventEmitter { constructor(options: IMapOptions) { super(); this.options = options; - const { minZoom, maxZoom, minPitch, maxPitch, renderWorldCopies } = options; + const { minZoom, maxZoom, minPitch, maxPitch, renderWorldCopies, crs } = + options; this.moving = false; this.zooming = false; this.bearingSnap = options.bearingSnap; @@ -77,6 +84,7 @@ export default class Camera extends EventEmitter { minPitch, maxPitch, renderWorldCopies, + crs, ); } // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -88,6 +96,10 @@ export default class Camera extends EventEmitter { return; } + public getCrs(): ICRS { + return this.transform.crs; + } + public getCenter() { const { lng, lat } = this.transform.center; return new LngLat(lng, lat); diff --git a/packages/map/src/earthmap.ts b/packages/map/src/earthmap.ts index 64030e0637..12fe20d66d 100644 --- a/packages/map/src/earthmap.ts +++ b/packages/map/src/earthmap.ts @@ -1,11 +1,15 @@ +import { + LngLat, + LngLatBounds, + LngLatBoundsLike, + LngLatLike, + Point, + PointLike, +} from '@antv/l7-core'; import { DOM } from '@antv/l7-utils'; import { merge } from 'lodash'; import Camera from './camera'; import './css/l7.css'; -import LngLat, { LngLatLike } from './geo/lng_lat'; -import LngLatBounds, { LngLatBoundsLike } from './geo/lng_lat_bounds'; -// @ts-ignore -import Point, { PointLike } from './geo/point'; import BoxZoomHandler from './handler/box_zoom'; import HandlerManager from './handler/handler_manager'; import KeyboardHandler from './handler/keyboard'; @@ -54,6 +58,7 @@ const DefaultOptions: IMapOptions = { renderWorldCopies: true, pitchEnabled: true, rotateEnabled: true, + crs: 'EPSG:3857', }; export class EarthMap extends Camera { public doubleClickZoom: DoubleClickZoomHandler; diff --git a/packages/map/src/geo/crs/crs.3857.ts b/packages/map/src/geo/crs/crs.3857.ts new file mode 100644 index 0000000000..b60853f082 --- /dev/null +++ b/packages/map/src/geo/crs/crs.3857.ts @@ -0,0 +1,12 @@ +import { ICRS, Transformation, TypeCRS } from '@antv/l7-core'; +import SphericalMercator from '../projection/sphericalMercator'; + +import Earth from './crs.earth'; +export default class EPSG3857 extends Earth implements ICRS { + public code: TypeCRS = 'EPSG:3857'; + public projection: SphericalMercator = new SphericalMercator(); + public transformation: Transformation = (() => { + const scale = 0.5 / (Math.PI * SphericalMercator.R); + return new Transformation(scale, 0.5, -scale, 0.5); + })(); +} diff --git a/packages/map/src/geo/crs/crs.earth.ts b/packages/map/src/geo/crs/crs.earth.ts new file mode 100644 index 0000000000..a7afbd3883 --- /dev/null +++ b/packages/map/src/geo/crs/crs.earth.ts @@ -0,0 +1,20 @@ +// https://github.com/Leaflet/Leaflet/blob/f0ca5bc9cf/src/geo/crs/CRS.Earth.js +import { ICRS, LngLat, TypeCRS } from '@antv/l7-core'; +import BaseCRS from './crs'; + +export default class Earth extends BaseCRS implements ICRS { + public code: TypeCRS = 'Earth'; + public wrapLng: [-180, 180]; + private R: number = 6378137; + public distance(lnglat1: LngLat, lnglat2: LngLat) { + const rad = Math.PI / 180; + const lat1 = lnglat1.lat * rad; + const lat2 = lnglat2.lat * rad; + const sinDLat = Math.sin(((lnglat2.lat - lnglat1.lat) * rad) / 2); + const sinDLon = Math.sin(((lnglat2.lng - lnglat1.lng) * rad) / 2); + const a = + sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon; + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return this.R * c; + } +} diff --git a/packages/map/src/geo/crs/crs.epsg4326.ts b/packages/map/src/geo/crs/crs.epsg4326.ts new file mode 100644 index 0000000000..a49b8467d9 --- /dev/null +++ b/packages/map/src/geo/crs/crs.epsg4326.ts @@ -0,0 +1,13 @@ +import { Transformation, TypeCRS } from '@antv/l7-core'; +import LngLatProjection from '../projection/lng_lat'; +import Earth from './crs.earth'; +export default class EPSG4326 extends Earth { + public code: TypeCRS = 'EPSG:4326'; + public projection: LngLatProjection = new LngLatProjection(); + public transformation: Transformation = new Transformation( + 1 / 180, + 1, + -1 / 180, + 0.5, + ); +} diff --git a/packages/map/src/geo/crs/crs.ts b/packages/map/src/geo/crs/crs.ts new file mode 100644 index 0000000000..d76e2ff81e --- /dev/null +++ b/packages/map/src/geo/crs/crs.ts @@ -0,0 +1,80 @@ +import { + Bounds, + ICRS, + ILngLat, + IPoint, + IProjection, + LngLat, + LngLatBounds, + LngLatLike, + Point, + Transformation, + TypeCRS, +} from '@antv/l7-core'; +import { wrap } from '@antv/l7-utils'; + +export default class BaseCRS implements ICRS { + private tileSize: number = 512; + public transformation: Transformation; + public projection: IProjection; + public wrapLng: [number, number]; + public wrapLat: [number, number]; + public code: TypeCRS; + // 空间是否限制 + public infinite: boolean = false; + // 经纬度转地图像素坐标 + public lngLatToPoint(lngLat: LngLatLike, zoom: number): Point { + const projectedPoint = this.projection.project(lngLat); + const scale = this.scale(zoom); + return this.transformation.transform(projectedPoint, scale); + } + public pointToLngLat(point: IPoint, zoom: number): LngLat { + const scale = this.scale(zoom); + const untransformedPoint = this.transformation.untransform(point, scale); + return this.projection.unproject(untransformedPoint); + } + // 经纬度转平面坐标 + public project(lngLat: ILngLat): Point { + return this.projection.project(lngLat); + } + + public unproject(point: IPoint): LngLat { + return this.projection.unproject(point); + } + + public scale(zoom: number): number { + return this.tileSize * Math.pow(2, zoom); + } + + public zoom(scale: number): number { + return Math.log(scale / this.tileSize) / Math.LN2; + } + + public getProjectedBounds(zoom: number): Bounds | null { + if (this.infinite) { + return null; + } + const b = this.projection.bounds; + const scale = this.scale(zoom); + const min = this.transformation.transform(b.min, scale); + const max = this.transformation.transform(b.max, scale); + return new Bounds(min, max); + } + + public wrapLnglat(lngLat: LngLat): LngLat { + const lng = this.wrapLng + ? wrap(lngLat.lng, this.wrapLng[0], this.wrapLng[1]) + : lngLat.lng; + + const lat = this.wrapLat + ? wrap(lngLat.lat, this.wrapLat[0], this.wrapLat[1]) + : lngLat.lat; + + return new LngLat(lat, lng); + } + public wrapLnglatBounds(lngLatBounds: LngLatBounds): LngLatBounds { + const sw = this.wrapLnglat(lngLatBounds.getSouthWest()); + const ne = this.wrapLnglat(lngLatBounds.getNorthEast()); + return new LngLatBounds(sw, ne); + } +} diff --git a/packages/map/src/geo/crs/index.ts b/packages/map/src/geo/crs/index.ts new file mode 100644 index 0000000000..4082ea39e4 --- /dev/null +++ b/packages/map/src/geo/crs/index.ts @@ -0,0 +1,18 @@ +import { ICRS, TypeCRS } from '@antv/l7-core'; +import BaseCRS from './crs'; +import EPSG3857 from './crs.3857'; +import Earth from './crs.earth'; +import EPSG4326 from './crs.epsg4326'; + +export function getCRS(name: TypeCRS): ICRS { + switch (name) { + case 'EPSG:3857': + return new EPSG3857(); + case 'EPSG:4326': + return new EPSG4326(); + default: + return new EPSG3857(); + } +} + +export { EPSG3857, EPSG4326, Earth, BaseCRS }; diff --git a/packages/map/src/geo/edge_insets.ts b/packages/map/src/geo/edge_insets.ts index dc6aa3ae92..7fe003f413 100644 --- a/packages/map/src/geo/edge_insets.ts +++ b/packages/map/src/geo/edge_insets.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { clamp, interpolate } from '../util'; -import Point from './point'; /** * An `EdgeInset` object represents screen space padding applied to the edges of the viewport. diff --git a/packages/map/src/geo/projection/lng_lat.ts b/packages/map/src/geo/projection/lng_lat.ts new file mode 100644 index 0000000000..2c10f233c5 --- /dev/null +++ b/packages/map/src/geo/projection/lng_lat.ts @@ -0,0 +1,21 @@ +import { + IPoint, + IProjection, + LngLat, + LngLatBounds, + LngLatBoundsLike, + LngLatLike, + Point, +} from '@antv/l7-core'; + +export default class LngLatProjection implements IProjection { + public bounds: LngLatBoundsLike = new LngLatBounds([-180, -90], [180, 90]); + public project(lngLat: LngLatLike): Point { + const { lng, lat } = LngLat.convert(lngLat); + return new Point(lng, lat); + } + + public unproject(point: IPoint): LngLat { + return new LngLat(point.x, point.y); + } +} diff --git a/packages/map/src/geo/projection/sphericalMercator.ts b/packages/map/src/geo/projection/sphericalMercator.ts new file mode 100644 index 0000000000..a870f665dd --- /dev/null +++ b/packages/map/src/geo/projection/sphericalMercator.ts @@ -0,0 +1,38 @@ +import { + Bounds, + IPoint, + IProjection, + LngLat, + LngLatLike, + Point, +} from '@antv/l7-core'; + +const earthRadius = 6378137; +export default class SphericalMercator implements IProjection { + public bounds: Bounds = (() => { + const d = earthRadius * Math.PI; + return new Bounds([-d, -d, d, d]); + })(); + public static R: number = earthRadius; + private maxLatitude: number = 85.0511287798; + + public project(ll: LngLatLike): Point { + const lngLat = LngLat.convert(ll); + const d = Math.PI / 180; + const max = this.maxLatitude; + const lat = Math.max(Math.min(max, lngLat.lat), -max); + const sin = Math.sin(lat * d); + return new Point( + earthRadius * lngLat.lng * d, + (earthRadius * Math.log((1 + sin) / (1 - sin))) / 2, + ); + } + + public unproject(point: IPoint): LngLat { + const d = 180 / Math.PI; + return new LngLat( + (point.x * d) / earthRadius, + (2 * Math.atan(Math.exp(point.y / earthRadius)) - Math.PI / 2) * d, + ); + } +} diff --git a/packages/map/src/geo/simple.ts b/packages/map/src/geo/simple.ts index 3f74c47714..73accbad53 100644 --- a/packages/map/src/geo/simple.ts +++ b/packages/map/src/geo/simple.ts @@ -1,4 +1,4 @@ -import LngLat, { earthRadius, LngLatLike } from '../geo/lng_lat'; +import { earthRadius, LngLat, LngLatLike } from '@antv/l7-core'; /* * The average circumference of the world in meters. diff --git a/packages/map/src/geo/transform.ts b/packages/map/src/geo/transform.ts index ae92cd6cd8..e7dec3d6f2 100644 --- a/packages/map/src/geo/transform.ts +++ b/packages/map/src/geo/transform.ts @@ -1,18 +1,25 @@ // @ts-ignore -import { isMini } from '@antv/l7-utils'; +import { + ICRS, + LngLat, + LngLatBounds, + MercatorCoordinate, + mercatorZfromAltitude, + Point, + TypeCRS, +} from '@antv/l7-core'; +import { isMini, wrap } from '@antv/l7-utils'; import { mat2, mat4, vec4 } from 'gl-matrix'; -import Point from '../geo/point'; -import { clamp, interpolate, wrap } from '../util'; +import { clamp, interpolate } from '../util'; +import { getCRS } from './crs'; import EdgeInsets, { IPaddingOptions } from './edge_insets'; -import LngLat from './lng_lat'; -import LngLatBounds from './lng_lat_bounds'; -import MercatorCoordinate, { - mercatorXfromLng, - mercatorYfromLat, - mercatorZfromAltitude, -} from './mercator'; + export const EXTENT = 8192; export default class Transform { + get crs(): ICRS { + return this._crs; + } + get minZoom(): number { return this._minZoom; } @@ -217,6 +224,7 @@ export default class Transform { private _minPitch: number; private _maxPitch: number; private _center: LngLat; + private _crs: ICRS; // tslint:enable private zoomFraction: number; private unmodified: boolean; @@ -230,6 +238,7 @@ export default class Transform { minPitch: number, maxPitch: number, renderWorldCopies: boolean | void, + crs: TypeCRS, ) { this.tileSize = 512; // constant this.maxValidLatitude = 85.051129; // constant @@ -257,6 +266,7 @@ export default class Transform { this.edgeInsets = new EdgeInsets(); this.posMatrixCache = {}; this.alignedPosMatrixCache = {}; + this._crs = getCRS(crs); } public clone(): Transform { @@ -266,6 +276,7 @@ export default class Transform { this._minPitch, this._maxPitch, this._renderWorldCopies, + this._crs.code, ); clone.tileSize = this.tileSize; clone.latRange = this.latRange; @@ -357,157 +368,6 @@ export default class Transform { // return result; // } - /** - * Return all coordinates that could cover this transform for a covering - * zoom level. - * @param {Object} options - * @param {number} options.tileSize - * @param {number} options.minzoom - * @param {number} options.maxzoom - * @param {boolean} options.roundZoom - * @param {boolean} options.reparseOverscaled - * @param {boolean} options.renderWorldCopies - * @returns {Array} OverscaledTileIDs - * @private - */ - // public coveringTiles(options: { - // tileSize: number; - // minzoom?: number; - // maxzoom?: number; - // roundZoom?: boolean; - // reparseOverscaled?: boolean; - // renderWorldCopies?: boolean; - // }): OverscaledTileID[] { - // let z = this.coveringZoomLevel(options); - // const actualZ = z; - - // if (options.minzoom !== undefined && z < options.minzoom) { - // return []; - // } - // if (options.maxzoom !== undefined && z > options.maxzoom) { - // z = options.maxzoom; - // } - - // const centerCoord = MercatorCoordinate.fromLngLat(this.center); - // const numTiles = Math.pow(2, z); - // const centerPoint = [numTiles * centerCoord.x, numTiles * centerCoord.y, 0]; - // const cameraFrustum = Frustum.fromInvProjectionMatrix( - // this.invProjMatrix, - // this.worldSize, - // z, - // ); - - // // No change of LOD behavior for pitch lower than 60 and when there is no top padding: return only tile ids from the requested zoom level - // let minZoom = options.minzoom || 0; - // // Use 0.1 as an epsilon to avoid for explicit == 0.0 floating point checks - // if (this._pitch <= 60.0 && this.edgeInsets.top < 0.1) { - // minZoom = z; - // } - - // // There should always be a certain number of maximum zoom level tiles surrounding the center location - // const radiusOfMaxLvlLodInTiles = 3; - - // const newRootTile = (wrap: number): any => { - // return { - // // All tiles are on zero elevation plane => z difference is zero - // aabb: new Aabb( - // [wrap * numTiles, 0, 0], - // [(wrap + 1) * numTiles, numTiles, 0], - // ), - // zoom: 0, - // x: 0, - // y: 0, - // wrap, - // fullyVisible: false, - // }; - // }; - - // // Do a depth-first traversal to find visible tiles and proper levels of detail - // const stack = []; - // const result = []; - // const maxZoom = z; - // const overscaledZ = options.reparseOverscaled ? actualZ : z; - - // if (this._renderWorldCopies) { - // // Render copy of the globe thrice on both sides - // for (let i = 1; i <= 3; i++) { - // stack.push(newRootTile(-i)); - // stack.push(newRootTile(i)); - // } - // } - - // stack.push(newRootTile(0)); - - // while (stack.length > 0) { - // const it = stack.pop(); - // const x = it.x; - // const y = it.y; - // let fullyVisible = it.fullyVisible; - - // // Visibility of a tile is not required if any of its ancestor if fully inside the frustum - // if (!fullyVisible) { - // const intersectResult = it.aabb.intersects(cameraFrustum); - - // if (intersectResult === 0) { - // continue; - // } - - // fullyVisible = intersectResult === 2; - // } - - // const distanceX = it.aabb.distanceX(centerPoint); - // const distanceY = it.aabb.distanceY(centerPoint); - // const longestDim = Math.max(Math.abs(distanceX), Math.abs(distanceY)); - - // // We're using distance based heuristics to determine if a tile should be split into quadrants or not. - // // radiusOfMaxLvlLodInTiles defines that there's always a certain number of maxLevel tiles next to the map center. - // // Using the fact that a parent node in quadtree is twice the size of its children (per dimension) - // // we can define distance thresholds for each relative level: - // // f(k) = offset + 2 + 4 + 8 + 16 + ... + 2^k. This is the same as "offset+2^(k+1)-2" - // const distToSplit = - // radiusOfMaxLvlLodInTiles + (1 << (maxZoom - it.zoom)) - 2; - - // // Have we reached the target depth or is the tile too far away to be any split further? - // if ( - // it.zoom === maxZoom || - // (longestDim > distToSplit && it.zoom >= minZoom) - // ) { - // result.push({ - // tileID: new OverscaledTileID( - // it.zoom === maxZoom ? overscaledZ : it.zoom, - // it.wrap, - // it.zoom, - // x, - // y, - // ), - // distanceSq: vec2.sqrLen([ - // centerPoint[0] - 0.5 - x, - // centerPoint[1] - 0.5 - y, - // ]), - // }); - // continue; - // } - - // for (let i = 0; i < 4; i++) { - // const childX = (x << 1) + (i % 2); - // const childY = (y << 1) + (i >> 1); - - // stack.push({ - // aabb: it.aabb.quadrant(i), - // zoom: it.zoom + 1, - // x: childX, - // y: childY, - // wrap: it.wrap, - // fullyVisible, - // }); - // } - // } - - // return result - // .sort((a, b) => a.distanceSq - b.distanceSq) - // .map((a) => a.tileID); - // } - public resize(width: number, height: number) { this.width = width; this.height = height; @@ -530,17 +390,12 @@ export default class Transform { -this.maxValidLatitude, this.maxValidLatitude, ); - return new Point( - mercatorXfromLng(lnglat.lng) * this.worldSize, - mercatorYfromLat(lat) * this.worldSize, - ); + + return this.crs.lngLatToPoint({ lng: lnglat.lng, lat }, this.zoom); } public unproject(point: Point): LngLat { - return new MercatorCoordinate( - point.x / this.worldSize, - point.y / this.worldSize, - ).toLngLat(); + return this.crs.pointToLngLat(point, this.zoom); } public setLocationAtPoint(lnglat: LngLat, point: Point) { @@ -581,7 +436,6 @@ export default class Transform { const z1 = coord1[2] / w1; const t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0); - return new MercatorCoordinate( interpolate(x0, x1, t) / this.worldSize, interpolate(y0, y1, t) / this.worldSize, @@ -743,10 +597,6 @@ export default class Transform { * @private */ public pointLocation(p: Point) { - // if(p.x !== 0 && p.x !== 1001) { - // console.log(p.x) - // } - return this.coordinateLocation(this.pointCoordinate(p)); } @@ -830,15 +680,15 @@ export default class Transform { const unmodified = this.unmodified; if (this.latRange) { const latRange = this.latRange; - minY = mercatorYfromLat(latRange[1]) * this.worldSize; - maxY = mercatorYfromLat(latRange[0]) * this.worldSize; + minY = this.crs.lngLatToPoint([0, latRange[1]], this.zoom).y; + maxY = this.crs.lngLatToPoint([0, latRange[0]], this.zoom).y; sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0; } if (this.lngRange) { const lngRange = this.lngRange; - minX = mercatorXfromLng(lngRange[0]) * this.worldSize; - maxX = mercatorXfromLng(lngRange[1]) * this.worldSize; + minX = this.crs.lngLatToPoint([lngRange[0], 0], this.zoom).x; + maxX = this.crs.lngLatToPoint([lngRange[1], 0], this.zoom).x; sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0; } diff --git a/packages/map/src/handler/IHandler.ts b/packages/map/src/handler/IHandler.ts index d31c059144..47fa19e825 100644 --- a/packages/map/src/handler/IHandler.ts +++ b/packages/map/src/handler/IHandler.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { EarthMap } from '../earthmap'; -import Point from '../geo/point'; import { Map } from '../map'; export interface IHandlerResult { panDelta?: Point; diff --git a/packages/map/src/handler/box_zoom.ts b/packages/map/src/handler/box_zoom.ts index bd92e3a49d..eac95ff215 100644 --- a/packages/map/src/handler/box_zoom.ts +++ b/packages/map/src/handler/box_zoom.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { EarthMap } from '../earthmap'; -import Point from '../geo/point'; import { Map } from '../map'; import DOM from '../utils/dom'; import { Event } from './events/event'; diff --git a/packages/map/src/handler/click_zoom.ts b/packages/map/src/handler/click_zoom.ts index fcdaf87d59..dbbd49dd76 100644 --- a/packages/map/src/handler/click_zoom.ts +++ b/packages/map/src/handler/click_zoom.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { EarthMap } from '../earthmap'; -import Point from '../geo/point'; import { Map } from '../map'; export default class ClickZoomHandler { diff --git a/packages/map/src/handler/events/map_mouse_event.ts b/packages/map/src/handler/events/map_mouse_event.ts index eb940b706b..b72b3f94af 100644 --- a/packages/map/src/handler/events/map_mouse_event.ts +++ b/packages/map/src/handler/events/map_mouse_event.ts @@ -1,9 +1,8 @@ // @ts-ignore // tslint:disable-next-line:no-submodule-imports +import { LngLat, Point } from '@antv/l7-core'; import merge from 'lodash/merge'; import { EarthMap } from '../../earthmap'; -import LngLat from '../../geo/lng_lat'; -import Point from '../../geo/point'; import { Map } from '../../map'; import DOM from '../../utils/dom'; import { Event } from './event'; diff --git a/packages/map/src/handler/events/map_touch_event.ts b/packages/map/src/handler/events/map_touch_event.ts index 9932405649..3ad1183182 100644 --- a/packages/map/src/handler/events/map_touch_event.ts +++ b/packages/map/src/handler/events/map_touch_event.ts @@ -1,7 +1,6 @@ // @ts-ignore +import { LngLat, Point } from '@antv/l7-core'; import { EarthMap } from '../../earthmap'; -import LngLat from '../../geo/lng_lat'; -import Point from '../../geo/point'; import { Map } from '../../map'; import DOM from '../../utils/dom'; import { Event } from './event'; diff --git a/packages/map/src/handler/handler_inertia.ts b/packages/map/src/handler/handler_inertia.ts index e9705e39a2..9b66e2893c 100644 --- a/packages/map/src/handler/handler_inertia.ts +++ b/packages/map/src/handler/handler_inertia.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../geo/point'; +import { Point } from '@antv/l7-core'; // tslint:disable-next-line:no-submodule-imports import merge from 'lodash/merge'; diff --git a/packages/map/src/handler/handler_manager.ts b/packages/map/src/handler/handler_manager.ts index 924860aebe..8ed3f7ea65 100644 --- a/packages/map/src/handler/handler_manager.ts +++ b/packages/map/src/handler/handler_manager.ts @@ -1,9 +1,9 @@ // @ts-ignore // tslint:disable-next-line: no-submodule-imports +import { Point } from '@antv/l7-core'; import { $window, isMini } from '@antv/l7-utils'; import { merge } from 'lodash'; import { EarthMap } from '../earthmap'; -import Point from '../geo/point'; import { Map } from '../map'; import DOM from '../utils/dom'; import BlockableMapEventHandler from './blockable_map_event'; diff --git a/packages/map/src/handler/handler_util.ts b/packages/map/src/handler/handler_util.ts index ab5060c9a9..2e63be829e 100644 --- a/packages/map/src/handler/handler_util.ts +++ b/packages/map/src/handler/handler_util.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../geo/point'; +import { Point } from '@antv/l7-core'; export function indexTouches(touches: Touch[], points: Point[]) { const obj: { [key: string]: any } = {}; diff --git a/packages/map/src/handler/map_event.ts b/packages/map/src/handler/map_event.ts index 40006b2b25..76ac076907 100644 --- a/packages/map/src/handler/map_event.ts +++ b/packages/map/src/handler/map_event.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { EarthMap } from '../earthmap'; -import Point from '../geo/point'; import { Map } from '../map'; import { MapMouseEvent, MapTouchEvent, MapWheelEvent } from './events'; diff --git a/packages/map/src/handler/mouse/mouse_handler.ts b/packages/map/src/handler/mouse/mouse_handler.ts index ce89a98626..9ce34d1467 100644 --- a/packages/map/src/handler/mouse/mouse_handler.ts +++ b/packages/map/src/handler/mouse/mouse_handler.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import DOM from '../../utils/dom'; import { buttonStillPressed } from './util'; export default class MouseHandler { diff --git a/packages/map/src/handler/mouse/mousepan_handler.ts b/packages/map/src/handler/mouse/mousepan_handler.ts index 3b6b352190..ebecea9b05 100644 --- a/packages/map/src/handler/mouse/mousepan_handler.ts +++ b/packages/map/src/handler/mouse/mousepan_handler.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import MouseHandler from './mouse_handler'; import { LEFT_BUTTON } from './util'; export default class MousePanHandler extends MouseHandler { diff --git a/packages/map/src/handler/mouse/mousepitch_hander.ts b/packages/map/src/handler/mouse/mousepitch_hander.ts index 70c4c9594c..2f98708b41 100644 --- a/packages/map/src/handler/mouse/mousepitch_hander.ts +++ b/packages/map/src/handler/mouse/mousepitch_hander.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import MouseHandler from './mouse_handler'; import { LEFT_BUTTON, RIGHT_BUTTON } from './util'; export default class MousePitchHandler extends MouseHandler { diff --git a/packages/map/src/handler/mouse/mouserotate_hander.ts b/packages/map/src/handler/mouse/mouserotate_hander.ts index 47b5a75e28..c2d5ac4f62 100644 --- a/packages/map/src/handler/mouse/mouserotate_hander.ts +++ b/packages/map/src/handler/mouse/mouserotate_hander.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import MouseHandler from './mouse_handler'; import { LEFT_BUTTON, RIGHT_BUTTON } from './util'; export default class MouseRotateHandler extends MouseHandler { diff --git a/packages/map/src/handler/scroll_zoom.ts b/packages/map/src/handler/scroll_zoom.ts index 0c113db979..1aa25be9a9 100644 --- a/packages/map/src/handler/scroll_zoom.ts +++ b/packages/map/src/handler/scroll_zoom.ts @@ -1,7 +1,6 @@ // @ts-ignore +import { LngLat, Point } from '@antv/l7-core'; import { EarthMap } from '../earthmap'; -import LngLat from '../geo/lng_lat'; -import Point from '../geo/point'; import { Map } from '../map'; import { bezier, ease, interpolate, now } from '../util'; import DOM from '../utils/dom'; diff --git a/packages/map/src/handler/tap/single_tap_recognizer.ts b/packages/map/src/handler/tap/single_tap_recognizer.ts index 81ba129bc8..96702d0fff 100644 --- a/packages/map/src/handler/tap/single_tap_recognizer.ts +++ b/packages/map/src/handler/tap/single_tap_recognizer.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import { indexTouches } from '../handler_util'; function getCentroid(points: Point[]) { diff --git a/packages/map/src/handler/tap/tap_drag_zoom.ts b/packages/map/src/handler/tap/tap_drag_zoom.ts index 2e8960af51..6cee40305c 100644 --- a/packages/map/src/handler/tap/tap_drag_zoom.ts +++ b/packages/map/src/handler/tap/tap_drag_zoom.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import { MAX_TAP_INTERVAL } from './single_tap_recognizer'; import TapRecognizer from './tap_recognizer'; diff --git a/packages/map/src/handler/tap/tap_recognizer.ts b/packages/map/src/handler/tap/tap_recognizer.ts index ee0c5c971b..608de83b9c 100644 --- a/packages/map/src/handler/tap/tap_recognizer.ts +++ b/packages/map/src/handler/tap/tap_recognizer.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import SingleTapRecognizer, { MAX_DIST, MAX_TAP_INTERVAL, diff --git a/packages/map/src/handler/tap/tap_zoom.ts b/packages/map/src/handler/tap/tap_zoom.ts index bedec2a2a0..9c58187c1b 100644 --- a/packages/map/src/handler/tap/tap_zoom.ts +++ b/packages/map/src/handler/tap/tap_zoom.ts @@ -1,6 +1,6 @@ // @ts-ignore +import { Point } from '@antv/l7-core'; import { EarthMap } from '../../earthmap'; -import Point from '../../geo/point'; import { Map } from '../../map'; import TapRecognizer from './tap_recognizer'; diff --git a/packages/map/src/handler/touch/touch_pan.ts b/packages/map/src/handler/touch/touch_pan.ts index 4cbf15bc8e..5620e544be 100644 --- a/packages/map/src/handler/touch/touch_pan.ts +++ b/packages/map/src/handler/touch/touch_pan.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import { indexTouches } from '../handler_util'; export default class TouchPanHandler { diff --git a/packages/map/src/handler/touch/touch_pitch.ts b/packages/map/src/handler/touch/touch_pitch.ts index 9710410708..6004337bbd 100644 --- a/packages/map/src/handler/touch/touch_pitch.ts +++ b/packages/map/src/handler/touch/touch_pitch.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import TwoTouchHandler from './two_touch'; function isVertical(vector: { x: number; y: number }) { diff --git a/packages/map/src/handler/touch/touch_rotate.ts b/packages/map/src/handler/touch/touch_rotate.ts index 93b9196514..2f35265798 100644 --- a/packages/map/src/handler/touch/touch_rotate.ts +++ b/packages/map/src/handler/touch/touch_rotate.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import TwoTouchHandler from './two_touch'; const ROTATION_THRESHOLD = 25; // pixels along circumference of touch circle diff --git a/packages/map/src/handler/touch/touch_zoom.ts b/packages/map/src/handler/touch/touch_zoom.ts index 94c0a98d45..067110724b 100644 --- a/packages/map/src/handler/touch/touch_zoom.ts +++ b/packages/map/src/handler/touch/touch_zoom.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import TwoTouchHandler from './two_touch'; const ZOOM_THRESHOLD = 0.1; diff --git a/packages/map/src/handler/touch/two_touch.ts b/packages/map/src/handler/touch/two_touch.ts index 841502022c..16236d1885 100644 --- a/packages/map/src/handler/touch/two_touch.ts +++ b/packages/map/src/handler/touch/two_touch.ts @@ -1,5 +1,5 @@ // @ts-ignore -import Point from '../../geo/point'; +import { Point } from '@antv/l7-core'; import DOM from '../../utils/dom'; export default class TwoTouchHandler { diff --git a/packages/map/src/index.ts b/packages/map/src/index.ts index 25c19e47d5..cc1055fcb2 100644 --- a/packages/map/src/index.ts +++ b/packages/map/src/index.ts @@ -1,4 +1,3 @@ export * from './earthmap'; -export * from './geo/mercator'; export * from './interface'; export * from './map'; diff --git a/packages/map/src/interface.ts b/packages/map/src/interface.ts index a6275807f6..2418c2cb54 100644 --- a/packages/map/src/interface.ts +++ b/packages/map/src/interface.ts @@ -1,4 +1,4 @@ -import { LngLatBoundsLike } from './geo/lng_lat_bounds'; +import { LngLatBoundsLike, TypeCRS } from '@antv/l7-core'; export interface IMapOptions { hash: boolean; @@ -32,4 +32,5 @@ export interface IMapOptions { pitchWithRotate: boolean; pitchEnabled: boolean; rotateEnabled: boolean; + crs: TypeCRS; } diff --git a/packages/map/src/map.ts b/packages/map/src/map.ts index 595786f417..9372c61b68 100644 --- a/packages/map/src/map.ts +++ b/packages/map/src/map.ts @@ -1,11 +1,15 @@ +import { + LngLat, + LngLatBounds, + LngLatBoundsLike, + LngLatLike, + Point, + PointLike, +} from '@antv/l7-core'; import { $window, DOM, isMini } from '@antv/l7-utils'; import { merge } from 'lodash'; import Camera from './camera'; import './css/l7.css'; -import LngLat, { LngLatLike } from './geo/lng_lat'; -import LngLatBounds, { LngLatBoundsLike } from './geo/lng_lat_bounds'; -// @ts-ignore -import Point, { PointLike } from './geo/point'; import BoxZoomHandler from './handler/box_zoom'; import HandlerManager from './handler/handler_manager'; import KeyboardHandler from './handler/keyboard'; @@ -55,6 +59,7 @@ const DefaultOptions: IMapOptions = { renderWorldCopies: true, pitchEnabled: true, rotateEnabled: true, + crs: 'EPSG:3857', }; export class Map extends Camera { public doubleClickZoom: DoubleClickZoomHandler; diff --git a/packages/map/src/utils/dom.ts b/packages/map/src/utils/dom.ts index 0eaa38e518..ac796ab600 100644 --- a/packages/map/src/utils/dom.ts +++ b/packages/map/src/utils/dom.ts @@ -1,6 +1,6 @@ -import { $window, isMini } from '@antv/l7-utils'; // @ts-ignore -import Point from '../geo/point'; +import { Point } from '@antv/l7-core'; +import { $window, isMini } from '@antv/l7-utils'; const DOM: { [key: string]: (...arg: any[]) => any; diff --git a/packages/maps/src/amap2/map.ts b/packages/maps/src/amap2/map.ts index 62f628acb1..42524bdaf3 100644 --- a/packages/maps/src/amap2/map.ts +++ b/packages/maps/src/amap2/map.ts @@ -5,8 +5,8 @@ import AMapLoader from '@amap/amap-jsapi-loader'; import { - Bounds, CoordinateSystem, + IBoundsArray, IMapCamera, IPoint, IViewport, @@ -160,7 +160,7 @@ export default class AMapService extends AMapBaseService { return 'amap2'; } - public getBounds(): Bounds { + public getBounds(): IBoundsArray { const bounds = this.map.getBounds(); // @ts-ignore diff --git a/packages/maps/src/map/map.ts b/packages/maps/src/map/map.ts index f76853751e..b2293af9d8 100644 --- a/packages/maps/src/map/map.ts +++ b/packages/maps/src/map/map.ts @@ -2,8 +2,8 @@ /** * MapboxService */ -import { CoordinateSystem, IMercator } from '@antv/l7-core'; -import { Map, MercatorCoordinate } from '@antv/l7-map'; +import { CoordinateSystem, IMercator, MercatorCoordinate } from '@antv/l7-core'; +import { Map } from '@antv/l7-map'; import { $window } from '@antv/l7-utils'; import { mat4, vec3 } from 'gl-matrix'; import { injectable } from 'inversify'; diff --git a/packages/maps/src/utils/BaseMapService.ts b/packages/maps/src/utils/BaseMapService.ts index 5730f10d74..6ed9f773d8 100644 --- a/packages/maps/src/utils/BaseMapService.ts +++ b/packages/maps/src/utils/BaseMapService.ts @@ -2,9 +2,10 @@ * MapboxService */ import { - Bounds, CoordinateSystem, + IBoundsArray, ICoordinateSystemService, + ICRS, IGlobalConfigService, ILngLat, IMapCamera, @@ -101,6 +102,10 @@ export default abstract class BaseMapService return this.map.getContainer(); } + public getCrs(): ICRS { + return this.map.getCrs(); + } + public getMapCanvasContainer(): HTMLElement { return this.map.getCanvasContainer() as HTMLElement; } @@ -143,8 +148,8 @@ export default abstract class BaseMapService return this.map.getBearing(); } - public getBounds(): Bounds { - return this.map.getBounds().toArray() as Bounds; + public getBounds(): IBoundsArray { + return this.map.getBounds().toArray() as IBoundsArray; } public getMinZoom(): number { @@ -177,7 +182,7 @@ export default abstract class BaseMapService this.panTo([x, y]); } - public fitBounds(bound: Bounds, fitBoundsOptions?: any): void { + public fitBounds(bound: IBoundsArray, fitBoundsOptions?: any): void { this.map.fitBounds(bound, fitBoundsOptions); } diff --git a/packages/maps/src/utils/amap/AMapBaseService.ts b/packages/maps/src/utils/amap/AMapBaseService.ts index c0c67a6401..99c49c6c07 100644 --- a/packages/maps/src/utils/amap/AMapBaseService.ts +++ b/packages/maps/src/utils/amap/AMapBaseService.ts @@ -3,8 +3,8 @@ */ import AMapLoader from '@amap/amap-jsapi-loader'; import { - Bounds, CoordinateSystem, + IBoundsArray, ICameraOptions, ICoordinateSystemService, IGlobalConfigService, @@ -217,7 +217,7 @@ export default abstract class AMapBaseService return 360 - this.map.getRotation(); } - public getBounds(): Bounds { + public getBounds(): IBoundsArray { // @ts-ignore const amapBound = this.map.getBounds().toBounds(); const NE = amapBound.getNorthEast(); @@ -266,7 +266,7 @@ export default abstract class AMapBaseService this.map.panBy(x, y); } - public fitBounds(extent: Bounds): void { + public fitBounds(extent: IBoundsArray): void { this.map.setBounds( new AMap.Bounds([extent[0][0], extent[0][1], extent[1][0], extent[1][1]]), ); diff --git a/packages/scene/src/IMapController.ts b/packages/scene/src/IMapController.ts index b70ba14b3b..a1b4158de1 100644 --- a/packages/scene/src/IMapController.ts +++ b/packages/scene/src/IMapController.ts @@ -1,10 +1,11 @@ import { - Bounds, + IBoundsArray, ICameraOptions, ILngLat, IPoint, + IPointArray, IStatusOptions, - Point, + LngLatArray, } from '@antv/l7-core'; export default interface IMapController { @@ -31,7 +32,7 @@ export default interface IMapController { /** * 获取当前地图可视区域 `[西南角、东北角]` */ - getBounds(): Bounds; + getBounds(): IBoundsArray; /** * 放大地图 @@ -46,7 +47,7 @@ export default interface IMapController { /** * 地图平移到指定点 `[x, y]` */ - panTo(p: Point): void; + panTo(p: IPointArray): void; /** * 地图平移到指定点 `[x, y]` @@ -56,7 +57,7 @@ export default interface IMapController { /** * 调整地图适合指定区域 */ - fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void; + fitBounds(bound: IBoundsArray, fitBoundsOptions?: unknown): void; getContainer(): HTMLElement | null; getSize(): [number, number]; @@ -70,7 +71,7 @@ export default interface IMapController { // control with raw map setRotation(rotation: number): void; - setZoomAndCenter(zoom: number, center: Point): void; + setZoomAndCenter(zoom: number, center: IPointArray): void; setCenter(center: [number, number], options?: ICameraOptions): void; setPitch(pitch: number): void; setZoom(zoom: number): void; @@ -78,9 +79,9 @@ export default interface IMapController { setMapStatus(option: Partial): void; // coordinates methods - pixelToLngLat(pixel: Point): ILngLat; - lngLatToPixel(lnglat: Point): IPoint; - containerToLngLat(pixel: Point): ILngLat; - lngLatToContainer(lnglat: Point): IPoint; + pixelToLngLat(pixel: IPointArray): ILngLat; + lngLatToPixel(lnglat: LngLatArray): IPoint; + containerToLngLat(pixel: IPointArray): ILngLat; + lngLatToContainer(lnglat: LngLatArray): IPoint; exportMap(type: 'jpg' | 'png'): Promise; } diff --git a/packages/scene/src/index.ts b/packages/scene/src/index.ts index cf3cd7bd71..1a21390b02 100644 --- a/packages/scene/src/index.ts +++ b/packages/scene/src/index.ts @@ -1,8 +1,8 @@ import { Logo } from '@antv/l7-component'; import { - Bounds, createLayerContainer, createSceneContainer, + IBoundsArray, ICameraOptions, IControl, IControlService, @@ -20,6 +20,7 @@ import { IMarkerLayer, IMarkerService, IPoint, + IPointArray, IPopup, IPopupService, IPostProcessingPass, @@ -27,7 +28,7 @@ import { ISceneConfig, ISceneService, IStatusOptions, - Point, + LngLatArray, SceneEventList, TYPES, } from '@antv/l7-core'; @@ -415,7 +416,7 @@ class Scene return this.mapService.getRotation(); } - public getBounds(): Bounds { + public getBounds(): IBoundsArray { return this.mapService.getBounds(); } @@ -430,7 +431,7 @@ class Scene this.mapService.zoomOut(); } - public panTo(p: Point): void { + public panTo(p: IPointArray): void { this.mapService.panTo(p); } @@ -444,7 +445,7 @@ class Scene public setZoom(zoom: number): void { this.mapService.setZoom(zoom); } - public fitBounds(bound: Bounds, options?: unknown): void { + public fitBounds(bound: IBoundsArray, options?: unknown): void { const { fitBoundsOptions, animate } = this.sceneService.getSceneConfig(); this.mapService.fitBounds( bound, @@ -456,7 +457,7 @@ class Scene ); } - public setZoomAndCenter(zoom: number, center: Point): void { + public setZoomAndCenter(zoom: number, center: IPointArray): void { this.mapService.setZoomAndCenter(zoom, center); } @@ -469,19 +470,19 @@ class Scene } // conversion Method - public pixelToLngLat(pixel: Point): ILngLat { + public pixelToLngLat(pixel: IPointArray): ILngLat { return this.mapService.pixelToLngLat(pixel); } - public lngLatToPixel(lnglat: Point): IPoint { + public lngLatToPixel(lnglat: LngLatArray): IPoint { return this.mapService.lngLatToPixel(lnglat); } - public containerToLngLat(pixel: Point): ILngLat { + public containerToLngLat(pixel: IPointArray): ILngLat { return this.mapService.containerToLngLat(pixel); } - public lngLatToContainer(lnglat: Point): IPoint { + public lngLatToContainer(lnglat: LngLatArray): IPoint { return this.mapService.lngLatToContainer(lnglat); } diff --git a/packages/site/docs/api/scene.zh.md b/packages/site/docs/api/scene.zh.md index 81b42bcb71..e455729852 100644 --- a/packages/site/docs/api/scene.zh.md +++ b/packages/site/docs/api/scene.zh.md @@ -1,7 +1,7 @@ --- title: 场景 Scene -description: 地图场景初始 -keywords: 地图 Scene +description: 地图场景初始 +keywords: 地图 Scene order: 0 redirect_from: - /zh/docs/api diff --git a/packages/site/docs/api/source/mvt.zh.md b/packages/site/docs/api/source/mvt.zh.md index eba8c0fe44..a2ca214ad4 100644 --- a/packages/site/docs/api/source/mvt.zh.md +++ b/packages/site/docs/api/source/mvt.zh.md @@ -89,3 +89,5 @@ const source = new Source( }, ); ``` + + diff --git a/packages/site/docs/api/source/rasterTile.zh.md b/packages/site/docs/api/source/rasterTile.zh.md index 1937a5b684..ea4001db06 100644 --- a/packages/site/docs/api/source/rasterTile.zh.md +++ b/packages/site/docs/api/source/rasterTile.zh.md @@ -145,3 +145,5 @@ const rasterSource = new Source( }, ); ``` + + diff --git a/packages/site/docs/api/source/rastertile.zh.md b/packages/site/docs/api/source/rastertile.zh.md index 1937a5b684..ea4001db06 100644 --- a/packages/site/docs/api/source/rastertile.zh.md +++ b/packages/site/docs/api/source/rastertile.zh.md @@ -145,3 +145,5 @@ const rasterSource = new Source( }, ); ``` + + diff --git a/packages/site/docs/api/source/source.zh.md b/packages/site/docs/api/source/source.zh.md index 823513a42a..652052d09e 100644 --- a/packages/site/docs/api/source/source.zh.md +++ b/packages/site/docs/api/source/source.zh.md @@ -272,6 +272,8 @@ source.getFeatureId('name', '张三'); layer.setData(data); ``` + + ### 数据类型 #### JSON diff --git a/packages/site/docs/api/source/tile/method.md b/packages/site/docs/api/source/tile/method.md new file mode 100644 index 0000000000..ee20fe3508 --- /dev/null +++ b/packages/site/docs/api/source/tile/method.md @@ -0,0 +1,45 @@ +### 瓦片source 方法 + +#### reloadAllTile + +重新加载瓦片,会重新请求数据,适用与动态瓦片场景,如瓦片数据发生了更新,或者瓦片Join 的数据发生了更新 + +```ts pure +source.reloadAllTile(); +``` + +#### reloadTilebyId + +重新加载特定瓦片的 + +参数 +- z 缩放等级 +- x 瓦片 x 坐标 +- y 瓦片有坐标 + +```ts pure +source.reloadTileById(z,x,y); +``` + +#### reloadTileByExtent + +根据经纬度范围更新瓦片 + +参数 + +- extent: 经纬范围 [minLng,minLat,maxLng,maxLat] +- zoom: 缩放等级 + +#### reloadTileByLnglat + +根据经纬度更新瓦片,经纬度坐标转换成瓦片坐标更新 + +- lng 经度 +- lat 纬度 +- zoom 缩放等级 + + +```tsx pure + +source.reloadTileByLnglat(112,30,10); +``` \ No newline at end of file diff --git a/packages/site/maptools/demo/world.tsx b/packages/site/maptools/demo/world.tsx index 9df117f4e6..652d0f2715 100644 --- a/packages/site/maptools/demo/world.tsx +++ b/packages/site/maptools/demo/world.tsx @@ -34,7 +34,6 @@ import './index.less'; import { defaultDataInfo, downloadDataType, - editionOptions, IDataInfo, layerOptions, lineLayerOptions, @@ -56,6 +55,7 @@ export default () => { data: { type: 'FeatureCollection', features: [] }, parser: { type: 'geojson' }, }); + const [linedata,setLineData] = useState(); const [lineLayerSource, setLineLayerSource] = useState({ data: { type: 'FeatureCollection', features: [] }, parser: { type: 'geojson' }, @@ -83,13 +83,14 @@ export default () => { }, []); - const getDownloadData = async () => { - return layerSource.data as FeatureCollection; + const getDownloadData = async (type?:string = 'fill') => { + return type === 'line' ? linedata : layerSource.data; + }; - const onDownload = async () => { + const onDownload = async (type:string) => { const { datatype, currentName } = dataInfo; - const data = await getDownloadData(); + const data = await getDownloadData(type); downloadData(currentName, data, datatype); }; const onDownloadSvg = async () => { @@ -98,8 +99,8 @@ export default () => { return downloadData(currentName, data, 'SVG'); }; - const onCopyData = async () => { - const data = (await getDownloadData()) as FeatureCollection; + const onCopyData = async (type) => { + const data = (await getDownloadData(type)) as FeatureCollection; navigator.clipboard.writeText(JSON.stringify(data)); message.success('复制成功'); }; @@ -124,6 +125,7 @@ export default () => { .then((res) => res.arrayBuffer()) .then((data) => { const jsonData = geobuf.decode(new Pbf(data)) as FeatureCollection; + setLineData(jsonData); const linedata1 = { // 确定边界 type: 'FeatureCollection', @@ -217,7 +219,7 @@ export default () => { />
- + {/* 版本: @@ -229,7 +231,7 @@ export default () => { options={editionOptions[dataInfo.sourceType]} /> - + */} @@ -243,7 +245,7 @@ export default () => { - 数据下载: + 面数据: + +