diff --git a/packages/core/src/services/source/ISourceService.ts b/packages/core/src/services/source/ISourceService.ts index af50fb23d0..b03fc5d887 100644 --- a/packages/core/src/services/source/ISourceService.ts +++ b/packages/core/src/services/source/ISourceService.ts @@ -61,6 +61,7 @@ export type IJsonData = IJsonItem[]; export interface ISource { data: IParserData; + center: [number, number]; parser: IParserCfg; transforms: ITransform[]; cluster: boolean; diff --git a/packages/layers/src/plugins/DataMappingPlugin.ts b/packages/layers/src/plugins/DataMappingPlugin.ts index 7af982f418..f12e8918ea 100644 --- a/packages/layers/src/plugins/DataMappingPlugin.ts +++ b/packages/layers/src/plugins/DataMappingPlugin.ts @@ -73,17 +73,17 @@ export default class DataMappingPlugin implements ILayerPlugin { // 过滤数据 if (filter?.needRemapping) { layer.setEncodedData( - this.mapping(attributes, filterData, undefined, bottomColor, layer), + this.mapping(layer, attributes, filterData, undefined, bottomColor), ); filter.needRemapping = false; } else { layer.setEncodedData( this.mapping( + layer, attributesToRemapping, filterData, layer.getEncodedData(), bottomColor, - layer, ), ); } @@ -110,7 +110,7 @@ export default class DataMappingPlugin implements ILayerPlugin { }); } layer.setEncodedData( - this.mapping(attributes, filterData, undefined, bottomColor, layer), + this.mapping(layer, attributes, filterData, undefined, bottomColor), ); // 对外暴露事件 layer.emit('dataUpdate', null); @@ -127,17 +127,17 @@ export default class DataMappingPlugin implements ILayerPlugin { } private mapping( + layer: ILayer, attributes: IStyleAttribute[], data: IParseDataItem[], predata?: IEncodeFeature[], minimumColor?: string, - layer?: ILayer, ): IEncodeFeature[] { const { arrow = { enable: false, }, - } = layer?.getLayerConfig() as ILineLayerStyleOptions; + } = layer.getLayerConfig() as ILineLayerStyleOptions; const mappedData = data.map((record: IParseDataItem, i) => { const preRecord = predata ? predata[i] : {}; const encodeRecord: IEncodeFeature = { @@ -187,7 +187,7 @@ export default class DataMappingPlugin implements ILayerPlugin { // console.log('mappedData', mappedData) // 调整数据兼容 Amap2.0 - this.adjustData2Amap2Coordinates(mappedData); + this.adjustData2Amap2Coordinates(mappedData, layer); // 调整数据兼容 SimpleCoordinates this.adjustData2SimpleCoordinates(mappedData); @@ -195,12 +195,16 @@ export default class DataMappingPlugin implements ILayerPlugin { return mappedData; } - private adjustData2Amap2Coordinates(mappedData: IEncodeFeature[]) { + private adjustData2Amap2Coordinates( + mappedData: IEncodeFeature[], + layer: ILayer, + ) { // 根据地图的类型判断是否需要对点位数据进行处理, 若是高德2.0则需要对坐标进行相对偏移 if ( mappedData.length > 0 && this.mapService.version === Version['GAODE2.x'] ) { + const layerCenter = this.getLayerCenter(layer); if (typeof mappedData[0].coordinates[0] === 'number') { // 单个的点数据 // @ts-ignore @@ -212,7 +216,11 @@ export default class DataMappingPlugin implements ILayerPlugin { // @ts-ignore d.originCoordinates = cloneDeep(d.coordinates); // 为了兼容高德1.x 需要保存一份原始的经纬度坐标数据(许多上层逻辑依赖经纬度数据) // @ts-ignore - d.coordinates = this.mapService.lngLatToCoord(d.coordinates); + // d.coordinates = this.mapService.lngLatToCoord(d.coordinates); + d.coordinates = this.mapService.lngLatToCoordByLayer( + d.coordinates, + layerCenter, + ); }); } else { // 连续的线、面数据 @@ -225,12 +233,21 @@ export default class DataMappingPlugin implements ILayerPlugin { // @ts-ignore d.originCoordinates = cloneDeep(d.coordinates); // 为了兼容高德1.x 需要保存一份原始的经纬度坐标数据(许多上层逻辑依赖经纬度数据) // @ts-ignore - d.coordinates = this.mapService.lngLatToCoords(d.coordinates); + // d.coordinates = this.mapService.lngLatToCoords(d.coordinates); + d.coordinates = this.mapService.lngLatToCoordsByLayer( + d.coordinates, + layerCenter, + ); }); } } } + private getLayerCenter(layer: ILayer) { + const source = layer.getSource(); + return source.center; + } + private adjustData2SimpleCoordinates(mappedData: IEncodeFeature[]) { if (mappedData.length > 0 && this.mapService.version === Version.SIMPLE) { mappedData.map((d) => { diff --git a/packages/layers/src/plugins/ShaderUniformPlugin.ts b/packages/layers/src/plugins/ShaderUniformPlugin.ts index 9ca5708368..a4dde95606 100644 --- a/packages/layers/src/plugins/ShaderUniformPlugin.ts +++ b/packages/layers/src/plugins/ShaderUniformPlugin.ts @@ -44,6 +44,11 @@ export default class ShaderUniformPlugin implements ILayerPlugin { this.coordinateSystemService.refresh(); if (version === 'GAODE2.x') { + const layerCenter = this.getLayerCenter(layer); + // @ts-ignore + this.mapService.map.customCoords.setCenter(layerCenter); + // @ts-ignore + this.mapService.setCustomCoordCenter(layerCenter); // @ts-ignore mvp = this.mapService.map.customCoords.getMVPMatrix(); // mvp = amapCustomCoords.getMVPMatrix() @@ -86,4 +91,9 @@ export default class ShaderUniformPlugin implements ILayerPlugin { // TODO:脏检查,决定是否需要渲染 }); } + + private getLayerCenter(layer: ILayer) { + const source = layer.getSource(); + return source.center; + } } diff --git a/packages/maps/src/amap2/map.ts b/packages/maps/src/amap2/map.ts index b941752588..dc52e74537 100644 --- a/packages/maps/src/amap2/map.ts +++ b/packages/maps/src/amap2/map.ts @@ -20,7 +20,7 @@ import { Point, TYPES, } from '@antv/l7-core'; -import { DOM } from '@antv/l7-utils'; +import { amap2Project, DOM } from '@antv/l7-utils'; import { mat4, vec2, vec3 } from 'gl-matrix'; import { inject, injectable } from 'inversify'; import 'reflect-metadata'; @@ -102,30 +102,55 @@ export default class AMapService */ public setCustomCoordCenter(center: [number, number]) { this.sceneCenter = center; - // @ts-ignore - this.sceneCenterMKT = this.map - // @ts-ignore - .getProjection() - .project(...this.sceneCenter); + this.sceneCenterMKT = amap2Project(...center); } public getCustomCoordCenter(): [number, number] { return this.sceneCenterMKT; } + + public lngLatToCoordByLayer( + lnglat: [number, number], + layerCenter: [number, number], + ) { + const layerCenterFlat = amap2Project(...layerCenter); + return this._sub(amap2Project(lnglat[0], lnglat[1]), layerCenterFlat); + } + + public lngLatToCoordsByLayer( + lnglatArray: number[][][] | number[][], + layerCenter: [number, number], + ): number[][][] | number[][] { + // @ts-ignore + return lnglatArray.map((lnglats) => { + if (typeof lnglats[0] === 'number') { + return this.lngLatToCoordByLayer( + lnglats as [number, number], + layerCenter, + ); + } else { + // @ts-ignore + return lnglats.map((lnglat) => { + return this.lngLatToCoordByLayer( + lnglat as [number, number], + layerCenter, + ); + }); + } + }); + } + /** * 根据数据的绘制中心转换经纬度数据 高德2.0 */ public lngLatToCoord(lnglat: [number, number]) { - // @ts-ignore - const proj = this.map.getProjection(); - const project = proj.project; // 单点 if (!this.sceneCenter) { // @ts-ignore this.map.customCoords.setCenter(lnglat); this.setCustomCoordCenter(lnglat); } - return this._sub(project(lnglat[0], lnglat[1]), this.sceneCenterMKT); + return this._sub(amap2Project(lnglat[0], lnglat[1]), this.sceneCenterMKT); } /** diff --git a/packages/source/src/source.ts b/packages/source/src/source.ts index 1d56dae248..8375f71b3f 100644 --- a/packages/source/src/source.ts +++ b/packages/source/src/source.ts @@ -35,7 +35,7 @@ function mergeCustomizer(objValue: any, srcValue: any) { export default class Source extends EventEmitter implements ISource { public data: IParserData; - + public center: [number, number]; // 数据范围 public extent: BBox; // 生命周期钩子 @@ -235,12 +235,17 @@ export default class Source extends EventEmitter implements ISource { this.data = sourceParser(this.originData, parser); // 计算范围 this.extent = extent(this.data.dataArray); + this.setCenter(this.extent); this.invalidExtent = this.extent[0] === this.extent[2] || this.extent[1] === this.extent[3]; // 瓦片数据 this.tileset = this.initTileset(); } + private setCenter(bbox: BBox) { + this.center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2]; + } + /** * 瓦片数据管理器 */ diff --git a/packages/utils/src/geo.ts b/packages/utils/src/geo.ts index 943956306a..464e263e38 100644 --- a/packages/utils/src/geo.ts +++ b/packages/utils/src/geo.ts @@ -186,6 +186,19 @@ export function unProjectFlat(px: number[]): [number, number] { const lng = x / d; return [lng, lat]; } + +export function amap2Project(lng: number, lat: number): [number, number] { + const r = 85.0511287798; + const Rg = Math.PI / 180; + const Tg = 6378137; + + lat = Math.max(Math.min(r, lat), -r); + lng *= Rg; + lat *= Rg; + lat = Math.log(Math.tan(Math.PI / 4 + lat / 2)); + return [lng * Tg, lat * Tg]; +} + export function lnglatDistance( coordinates1: [number, number], coordinates2: [number, number], diff --git a/stories/Map/components/amap2demo.tsx b/stories/Map/components/amap2demo.tsx index b758cacc2f..56853caddf 100644 --- a/stories/Map/components/amap2demo.tsx +++ b/stories/Map/components/amap2demo.tsx @@ -1,4 +1,4 @@ -import { PointLayer, Scene } from '@antv/l7'; +import { PointLayer, Scene, LineLayer } from '@antv/l7'; import { GaodeMapV2 } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo extends React.Component { @@ -13,147 +13,86 @@ export default class Amap2demo extends React.Component { const scene = new Scene({ id: 'map', map: new GaodeMapV2({ - center: [121.107846, 30.267069], + // center: [121.107846, 30.267069], + center: [120.692587367181758, 30.377451929339649], pitch: 0, style: 'normal', zoom: 20, animateEnable: false, + zooms: [0, 23], }), }); - let originData = [ - { - lng: 121.107846, - lat: 30.267069, - opacity2: 0.2, - strokeOpacity2: 0.4, - strokeColor: '#000', - strokeWidth: 0.5, - // offsets2: [0, 0] - offsets2: [100, 100], - }, - { - lng: 121.107, - lat: 30.267069, - opacity2: 0.4, - strokeOpacity2: 0.6, - strokeColor: '#0f0', - strokeWidth: 2, - offsets2: [100, 100], - }, - { - lng: 121.107846, - lat: 30.26718, - opacity2: 0.6, - strokeOpacity2: 0.8, - strokeColor: '#f00', - strokeWidth: 4, - // offsets2: [200, 200] - offsets2: [100, 100], - }, - // { - // lng: 38.54, - // lat: 77.02, - // opacity: 0.5 - // strokeColor: "#ff0" - // }, - ]; - this.scene = scene; - // https://gw-office.alipayobjects.com/bmw-prod/61c3fca0-2991-48b4-bb6d-ecc2cbd682dd.json // 100 * 100 - let hunredMhunred = - 'https://gw-office.alipayobjects.com/bmw-prod/61c3fca0-2991-48b4-bb6d-ecc2cbd682dd.json'; - // https://gw-office.alipayobjects.com/bmw-prod/ccc91465-d3ea-4eda-a178-7c1815dac32b.json // 1000 * 100 - let thousandMhundred = - 'https://gw-office.alipayobjects.com/bmw-prod/ccc91465-d3ea-4eda-a178-7c1815dac32b.json'; + let data = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [122.692587367181758, 43.377451929339649], + [122.692587367181758, 43.377465856847415], + [122.692574277855613, 43.377465856847415], + [122.692574277855613, 43.377451929339649], + [122.692587367181758, 43.377451929339649], + ], + ], + }, + }, + ], + }; + // let cut = 0.0002; + let data2 = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [120.692587367181758, 30.377451929339649], + [120.692587367181758, 30.377465856847415], + [120.692574277855613, 30.377465856847415], + [120.692574277855613, 30.377451929339649], + [120.692587367181758, 30.377451929339649], + ], + ], + }, + }, + ], + }; scene.on('loaded', () => { - for (let i = 0; i < 1; i++) { - // fetch(thousandMhundred) - // .then((res) => res.text()) - // .then((data) => { - // // console.log('data', data) - // // lng: Math.random() * 180, // 0 ~ 180 - // // lat: Math.random() * 100 - 50, // -50 ~ 50 - // // customOpacity: Math.random(), - // // customStroke: `rgb(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 1)`, - // // customStrokeOpacity: Math.random(), - // // customStrokeWidth: Math.random() * 5, - // let layer = new PointLayer() - // .source(JSON.parse(data), { - // parser: { - // type: 'json', - // x: 'lng', - // y: 'lat', - // }, - // }) - // .shape('circle') - // .color('rgba(255, 0, 0, 1.0)') - // .size(10) - // .style({ - // opacity: 'customOpacity', - // // strokeOpacity: 'customStrokeOpacity', - // // strokeWidth: 'customStrokeWidth', - // // stroke: 'customStroke', - // }); - // scene.addLayer(layer); - // }); - let layer = new PointLayer() - .source(originData, { - parser: { - type: 'json', - x: 'lng', - y: 'lat', - }, - }) - .shape('circle') - // .shape('normal') - // .color('rgba(255, 0, 0, 0.9)') - // .shape('cylinder') - .color('rgba(255, 0, 0, 1.0)') - // .size(10) - .size([10, 10, 100]) - // .offsets('123') - .style({ - // stroke: '#000', - // stroke: 'rgba(0, 255, 0, 1)', - // stroke: 'strokeColor', - // stroke: ['strokeColor', (d: any) => { - // return d - // }], - // stroke: ['strokeColor', ["#f00", "#ff0"]], - - strokeWidth: 4, - // strokeWidth: "strokeWidth", - // strokeWidth: ["strokeWidth", [1, 2]], - // strokeWidth: ["strokeWidth", (d: any) => { - // return d * 2 - // }], - - // strokeOpacity: 0.5, - // strokeOpacity: 'strokeOpacity2', - // strokeOpacity: 1.0, - // strokeOpacity: [ - // 'strokeOpacity2', - // (d: any) => { - // // console.log('strokeOpacity2', d) - // return d*2; - // }, - // ], - // strokeOpacity: ['opacity2', [0.2, 0.6]], - - // offsets: [100, 100], - // offsets: 'offsets2', - // offsets: ['offsets2', (d: any) => d], - - opacity: 'opacity2', - // opacity: 0.2 - // opacity: 0, - // opacity: ['opacity2', (d: any) => { - // return d - // }] - // opacity: ['opacity2', [0.2, 0.6]], - }) - .active(true); - scene.addLayer(layer); - } + let rect = new LineLayer() + .source(data) + .shape('line') + .size(2) + .color('#f00'); + scene.addLayer(rect); + let rect2 = new LineLayer() + .source(data2) + .shape('line') + .size(2) + .color('#f00'); + scene.addLayer(rect2); + const mapService = scene.getMapService(); + // setTimeout(() => { + // scene.setCenter([122.692587367181758, 43.377451929339649]); + // // // @ts-ignore + // // mapService.map.customCoords?.setCenter([ + // // 122.692587367181758, + // // 43.377451929339649, + // // ]); + // // // @ts-ignore + // // mapService.setCustomCoordCenter([ + // // 122.692587367181758, + // // 43.377451929339649, + // // ]); + // // rect.dataState.dataSourceNeedUpdate = true; + // }, 2000); }); }