From 0fdb6d1b0dd16f9dcb1c7c6f547017af8c5b46a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=8A=E9=92=B1=E8=80=80?= Date: Thu, 22 Apr 2021 15:08:41 +0800 Subject: [PATCH 1/9] feat(many): gaode1.x -> gaode2.0 not finished --- .../coordinate/CoordinateSystemService.ts | 5 + .../coordinate/ICoordinateSystemService.ts | 3 + packages/core/src/services/map/IMapService.ts | 11 + .../core/src/services/scene/SceneService.ts | 28 +- packages/core/src/shaders/projection.glsl | 39 +- packages/layers/src/core/triangulation.ts | 50 +- .../src/line/shaders/line_arc_vert.glsl | 9 +- .../layers/src/line/shaders/line_vert.glsl | 11 +- .../layers/src/plugins/DataMappingPlugin.ts | 37 +- .../layers/src/plugins/DataSourcePlugin.ts | 9 +- .../layers/src/plugins/ShaderUniformPlugin.ts | 25 +- packages/layers/src/point/index.ts | 1 - packages/layers/src/point/models/fill.ts | 2 +- packages/layers/src/point/models/text.ts | 24 +- .../src/point/shaders/extrude_vert.glsl | 9 +- .../layers/src/point/shaders/fill_vert.glsl | 26 +- .../layers/src/point/shaders/image_vert.glsl | 10 +- .../layers/src/point/shaders/normal_vert.glsl | 18 +- .../layers/src/point/shaders/text_vert.glsl | 27 +- .../polygon/shaders/polygon_extrude_vert.glsl | 10 +- .../src/polygon/shaders/polygon_vert.glsl | 9 +- packages/layers/src/utils/extrude_polyline.ts | 349 ++++++++++ packages/maps/src/amap/map.ts | 5 +- packages/maps/src/amap2/Viewport.ts | 124 ++++ packages/maps/src/amap2/index.ts | 11 + packages/maps/src/amap2/logo.css | 3 + packages/maps/src/amap2/map.ts | 625 ++++++++++++++++++ packages/maps/src/amap2/theme.ts | 8 + packages/maps/src/index.ts | 3 +- packages/maps/src/map/map.ts | 3 +- packages/maps/src/mapbox/map.ts | 3 +- packages/maps/src/version.ts | 9 + packages/maps/typings/index.d.ts | 7 + packages/source/src/source.ts | 4 +- stories/Map/components/amap2demo.tsx | 88 +++ stories/Map/components/amap2demo_arcLine.tsx | 74 +++ stories/Map/components/amap2demo_extrude.tsx | 84 +++ stories/Map/components/amap2demo_image.tsx | 80 +++ stories/Map/components/amap2demo_polygon.tsx | 140 ++++ .../components/amap2demo_polygon_extrude.tsx | 132 ++++ stories/Map/components/amap2demo_text.tsx | 80 +++ stories/Map/components/amapdemo_extrude.tsx | 84 +++ stories/Map/components/mapCenter.tsx | 40 +- stories/Map/map.stories.tsx | 20 +- 44 files changed, 2253 insertions(+), 86 deletions(-) create mode 100644 packages/maps/src/amap2/Viewport.ts create mode 100644 packages/maps/src/amap2/index.ts create mode 100644 packages/maps/src/amap2/logo.css create mode 100644 packages/maps/src/amap2/map.ts create mode 100644 packages/maps/src/amap2/theme.ts create mode 100644 packages/maps/src/version.ts create mode 100644 stories/Map/components/amap2demo.tsx create mode 100644 stories/Map/components/amap2demo_arcLine.tsx create mode 100644 stories/Map/components/amap2demo_extrude.tsx create mode 100644 stories/Map/components/amap2demo_image.tsx create mode 100644 stories/Map/components/amap2demo_polygon.tsx create mode 100644 stories/Map/components/amap2demo_polygon_extrude.tsx create mode 100644 stories/Map/components/amap2demo_text.tsx create mode 100644 stories/Map/components/amapdemo_extrude.tsx diff --git a/packages/core/src/services/coordinate/CoordinateSystemService.ts b/packages/core/src/services/coordinate/CoordinateSystemService.ts index 8bf04809dc..cbd2f400b5 100644 --- a/packages/core/src/services/coordinate/CoordinateSystemService.ts +++ b/packages/core/src/services/coordinate/CoordinateSystemService.ts @@ -3,6 +3,7 @@ import { inject, injectable } from 'inversify'; import { TYPES } from '../../types'; import { getDistanceScales } from '../../utils/project'; import { ICameraService } from '../camera/ICameraService'; +// import { IMapService } from '../map/IMapService' import { CoordinateSystem, ICoordinateSystemService, @@ -17,6 +18,10 @@ export default class CoordinateSystemService @inject(TYPES.ICameraService) private readonly cameraService: ICameraService; + // map.getCenter + // @inject(TYPES.IMapService) + // private readonly mapService: IMapService + /** * 1. Web 墨卡托坐标系 * 2. 偏移经纬度,用于解决高精度抖动问题 diff --git a/packages/core/src/services/coordinate/ICoordinateSystemService.ts b/packages/core/src/services/coordinate/ICoordinateSystemService.ts index 8bbc211970..ca3e0f2d6f 100644 --- a/packages/core/src/services/coordinate/ICoordinateSystemService.ts +++ b/packages/core/src/services/coordinate/ICoordinateSystemService.ts @@ -17,6 +17,7 @@ export enum CoordinateSystem { P20 = 5.0, P20_OFFSET = 6.0, METER_OFFSET = 7.0, + P20_2 = 8.0, } // 后续传入 Shader 的变量 @@ -27,6 +28,8 @@ export const CoordinateUniform = { PixelsPerDegree: 'u_PixelsPerDegree', PixelsPerDegree2: 'u_PixelsPerDegree2', PixelsPerMeter: 'u_PixelsPerMeter', + + Mvp: 'u_Mvp', }; export interface ICoordinateSystemService { diff --git a/packages/core/src/services/map/IMapService.ts b/packages/core/src/services/map/IMapService.ts index 6207cbb9e9..fe307857ac 100644 --- a/packages/core/src/services/map/IMapService.ts +++ b/packages/core/src/services/map/IMapService.ts @@ -30,8 +30,10 @@ export interface IMapWrapper { } export interface IMapService { + version: string; map: RawMap; init(): void; + initViewPort?(): void; destroy(): void; onCameraChanged(callback: (viewport: IViewport) => void): void; // init map @@ -85,6 +87,12 @@ export interface IMapService { scale: [number, number, number], origin: IMercator, ): number[]; + lngLatToCoord?(lnglat: [number, number]): [number, number]; + lngLatToCoords?( + lnglatArray: number[][][] | number[][], + ): number[][][] | number[][] | number[][][] | number[][]; + // lngLatToCoords?(lnglatArray: any): any; + getCustomCoordCenter?(): [number, number]; exportMap(type: 'jpg' | 'png'): string; } @@ -178,6 +186,9 @@ export interface IMapCamera { center: [number, number]; // 相机高度 cameraHeight: number; + cameraPosition?: [number, number, number]; + up?: [number, number, number]; + lookAt?: [number, number, number]; // 偏移原点,例如 P20 坐标系下 offsetOrigin: [number, number]; } diff --git a/packages/core/src/services/scene/SceneService.ts b/packages/core/src/services/scene/SceneService.ts index eb94c3fdae..75c0fcc246 100644 --- a/packages/core/src/services/scene/SceneService.ts +++ b/packages/core/src/services/scene/SceneService.ts @@ -139,15 +139,32 @@ export default class Scene extends EventEmitter implements ISceneService { */ this.hooks.init.tapPromise('initMap', async () => { // 等待首次相机同步 - await new Promise((resolve) => { + await new Promise((resolve) => { this.map.onCameraChanged((viewport: IViewport) => { this.cameraService.init(); this.cameraService.update(viewport); - resolve(); + if (this.map.version !== 'GAODE2.x') { + // not amap2 + resolve(); + } }); - this.map.init(); + + if (this.map.version !== 'GAODE2.x') { + // not amap2 + this.map.init(); + } else { + // amap2 + resolve(); + } }); + + if (this.map.version === 'GAODE2.x' && this.map.initViewPort) { + // amap2 + await this.map.init(); + this.map.initViewPort(); + } // this.controlService.addControls(); + // 重新绑定非首次相机更新事件 this.map.onCameraChanged(this.handleMapCameraChanged); this.map.addMarkerContainer(); @@ -208,7 +225,6 @@ export default class Scene extends EventEmitter implements ISceneService { // 执行异步并行初始化任务 // @ts-ignore this.initPromise = this.hooks.init.promise(); - this.render(); } @@ -222,11 +238,11 @@ export default class Scene extends EventEmitter implements ISceneService { if (this.rendering || this.destroyed) { return; } - this.rendering = true; // 首次初始化,或者地图的容器被强制销毁的需要重新初始化 if (!this.inited) { // 还未初始化完成需要等待 + await this.initPromise; if (this.destroyed) { this.destroy(); @@ -243,9 +259,7 @@ export default class Scene extends EventEmitter implements ISceneService { // 尝试初始化未初始化的图层 this.layerService.renderLayers(); // 组件需要等待layer 初始化完成之后添加 - this.logger.debug(`scene ${this.id} render`); - this.rendering = false; } diff --git a/packages/core/src/shaders/projection.glsl b/packages/core/src/shaders/projection.glsl index 0ecd325e51..c5eadf8143 100644 --- a/packages/core/src/shaders/projection.glsl +++ b/packages/core/src/shaders/projection.glsl @@ -10,6 +10,8 @@ #define COORDINATE_SYSTEM_P20_OFFSET 6.0 #define COORDINATE_SYSTEM_METER_OFFSET 7.0 +#define COORDINATE_SYSTEM_P20_2 8.0 + uniform mat4 u_ViewMatrix; uniform mat4 u_ProjectionMatrix; uniform mat4 u_ViewProjectionMatrix; @@ -28,6 +30,8 @@ uniform float u_DevicePixelRatio; uniform float u_FocalDistance; uniform vec3 u_CameraPosition; +// uniform mat4 u_Mvp; + // web mercator coords -> world coords vec2 project_mercator(vec2 lnglat) { float x = lnglat.x; @@ -38,7 +42,13 @@ vec2 project_mercator(vec2 lnglat) { } float project_scale(float meters) { - return meters * u_PixelsPerMeter.z; + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { + // 因为高德2.0和1.x的相机控制方向相反,而u_PixelsPerMeter的计算与此相关(计算结果也相反) + // 可通过 shaderUniformPlugin -> CoordinateSystemService -> project 的顺序查看区别 + return meters * u_PixelsPerMeter.z * -1.0; + } else { + return meters * u_PixelsPerMeter.z; + } } @@ -69,6 +79,10 @@ vec3 reverse_offset_normal(vec3 vector) { if (u_CoordinateSystem == COORDINATE_SYSTEM_P20 ||u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET ) { return vector * vec3(1.0, -1.0, 1.0); } + + if (u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.0 + return vector * vec3(1.0, -1.0, 1.0); + } return vector; } @@ -97,6 +111,17 @@ vec4 project_position(vec4 position) { position.w ); } + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { + // return vec4( + // (position.xy * WORLD_SCALE * u_ZoomScale) * vec2(1., -1.), + // project_scale(position.z), + // position.w); + return vec4( + position.xy, + project_scale(position.z), + position.w); + } return position; // TODO: 瓦片坐标系 & 常规世界坐标系 @@ -111,6 +136,10 @@ float project_pixel(float pixel) { // P20 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减1 return pixel * pow(2.0, (19.0 - u_Zoom)); } + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { + // P20_2 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减3 + return pixel * pow(2.0, (19.0 - 3.0 - u_Zoom)); + } return pixel; } vec2 project_pixel(vec2 pixel) { @@ -118,6 +147,10 @@ vec2 project_pixel(vec2 pixel) { // P20 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减1 return pixel * pow(2.0, (19.0 - u_Zoom)); } + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { + // P20_2 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减3 + return pixel * pow(2.0, (19.0 - 3.0 - u_Zoom)); + } return pixel * -1.; } @@ -127,6 +160,7 @@ vec4 project_common_position_to_clipspace(vec4 position, mat4 viewProjectionMatr // Needs to be divided with project_uCommonUnitsPerMeter position.w *= u_PixelsPerMeter.z; } + return viewProjectionMatrix * position + center; } @@ -153,5 +187,4 @@ vec4 unproject_clipspace_to_position(vec4 clipspacePos, mat4 u_InverseViewProjec bool isEqual( float a, float b) { return a< b + 0.001 && a > b - 0.001; -} - +} \ No newline at end of file diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index c95eebf878..dfd266c3eb 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -69,19 +69,48 @@ export function PointImageTriangulation(feature: IEncodeFeature) { * @param feature 映射feature */ export function LineTriangulation(feature: IEncodeFeature) { - const { coordinates } = feature; - let path = coordinates as number[][][] | number[][]; - if (!Array.isArray(path[0][0])) { - path = [coordinates] as number[][][]; - } + const { coordinates, originCoordinates, version } = feature; + // let path = coordinates as number[][][] | number[][]; + // if (!Array.isArray(path[0][0])) { + // path = [coordinates] as number[][][]; + // } + const line = new ExtrudePolyline({ dash: true, - join: 'bevel', // - }); - path.forEach((item: any) => { - // 处理带洞的多边形 - line.extrude(item as number[][]); + join: 'bevel', }); + + if (version === 'GAODE2.x') { + // 处理高德2.0几何体构建 + let path1 = coordinates as number[][][] | number[][]; + if (!Array.isArray(path1[0][0])) { + path1 = [coordinates] as number[][][]; + } + let path2 = originCoordinates as number[][][] | number[][]; + if (!Array.isArray(path2[0][0])) { + path2 = [originCoordinates] as number[][][]; + } + + path1.forEach((item: any) => { + // 处理带洞的多边形 + line.extrude1(item as number[][]); + }); + + path2.forEach((item: any) => { + // 处理带洞的多边形 + line.extrude2(item as number[][]); + }); + } else { + // 处理非高德2.0的几何体构建 + let path = coordinates as number[][][] | number[][]; + if (!Array.isArray(path[0][0])) { + path = [coordinates] as number[][][]; + } + path.forEach((item: any) => { + line.extrude(item as number[][]); + }); + } + const linebuffer = line.complex; return { vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ] @@ -207,6 +236,7 @@ export function LineArcTriangulation(feature: IEncodeFeature) { ); } } + // console.log('positions', positions) return { vertices: positions, indices: indexArray, diff --git a/packages/layers/src/line/shaders/line_arc_vert.glsl b/packages/layers/src/line/shaders/line_arc_vert.glsl index 5fcbcfd42a..013c210346 100644 --- a/packages/layers/src/line/shaders/line_arc_vert.glsl +++ b/packages/layers/src/line/shaders/line_arc_vert.glsl @@ -6,6 +6,7 @@ attribute vec3 a_Position; attribute vec4 a_Instance; attribute float a_Size; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; uniform float segmentNumber; uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; varying vec4 v_color; @@ -78,8 +79,14 @@ void main() { vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0)); vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0)); v_normal = getNormal((next.xy - curr.xy) * indexDir, a_Position.y); + vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y)); - gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); + // gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * (vec4(curr.xy + offset, 0, 1.0)); + } else { + gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); + } setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/line/shaders/line_vert.glsl b/packages/layers/src/line/shaders/line_vert.glsl index 7b0495a44d..848948b3a0 100644 --- a/packages/layers/src/line/shaders/line_vert.glsl +++ b/packages/layers/src/line/shaders/line_vert.glsl @@ -13,6 +13,7 @@ attribute float a_Total_Distance; attribute float a_Distance; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; uniform float u_line_type: 0.0; uniform vec4 u_dash_array: [10.0, 5.,0, 0]; uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; @@ -42,7 +43,15 @@ void main() { vec2 offset = project_pixel(size.xy); v_side = a_Miter * a_Size.x; vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0)); - gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, a_Size.y, 1.0)); + + // gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, a_Size.y, 1.0)); + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + // gl_Position = u_Mvp * (vec4(project_pos.xy + offset, a_Size.y, 1.0)); + gl_Position = u_Mvp * (vec4(project_pos.xy + offset, a_Size.y, 1.0)); + } else { + gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, a_Size.y, 1.0)); + } setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/plugins/DataMappingPlugin.ts b/packages/layers/src/plugins/DataMappingPlugin.ts index cdc8082b4e..86ab15bc87 100644 --- a/packages/layers/src/plugins/DataMappingPlugin.ts +++ b/packages/layers/src/plugins/DataMappingPlugin.ts @@ -3,7 +3,9 @@ import { IGlobalConfigService, ILayer, ILayerPlugin, + ILngLat, ILogService, + IMapService, IParseDataItem, IStyleAttribute, IStyleAttributeService, @@ -11,6 +13,7 @@ import { } from '@antv/l7-core'; import { rgb2arr } from '@antv/l7-utils'; import { inject, injectable } from 'inversify'; +import { cloneDeep } from 'lodash'; @injectable() export default class DataMappingPlugin implements ILayerPlugin { @@ -20,6 +23,9 @@ export default class DataMappingPlugin implements ILayerPlugin { @inject(TYPES.ILogService) private readonly logger: ILogService; + @inject(TYPES.IMapService) + private readonly mapService: IMapService; + public apply( layer: ILayer, { @@ -99,7 +105,7 @@ export default class DataMappingPlugin implements ILayerPlugin { data: IParseDataItem[], predata?: IEncodeFeature[], ): IEncodeFeature[] { - return data.map((record: IParseDataItem, i) => { + const mappedData = data.map((record: IParseDataItem, i) => { const preRecord = predata ? predata[i] : {}; const encodeRecord: IEncodeFeature = { id: record._id, @@ -124,6 +130,35 @@ export default class DataMappingPlugin implements ILayerPlugin { }); return encodeRecord; }) as IEncodeFeature[]; + + // console.log('mappedData', mappedData) + // 根据地图的类型判断是否需要对点位数据进行处理 + if (this.mapService.version === 'GAODE2.x') { + // 若是高德2.0则需要对坐标进行相对偏移 + + if (typeof mappedData[0].coordinates[0] === 'number') { + // 单个的点数据 + // @ts-ignore + mappedData.map((d) => { + d.version = 'GAODE2.x'; + // @ts-ignore + d.originCoordinates = cloneDeep(d.coordinates); // 为了兼容高德1.x 需要保存一份原始的经纬度坐标数据(许多上层逻辑依赖经纬度数据) + // @ts-ignore + d.coordinates = this.mapService.lngLatToCoord(d.coordinates); + }); + } else { + // 连续的线、面数据 + // @ts-ignore + mappedData.map((d) => { + d.version = 'GAODE2.x'; + // @ts-ignore + d.originCoordinates = cloneDeep(d.coordinates); // 为了兼容高德1.x 需要保存一份原始的经纬度坐标数据(许多上层逻辑依赖经纬度数据) + // @ts-ignore + d.coordinates = this.mapService.lngLatToCoords(d.coordinates); + }); + } + } + return mappedData; } private applyAttributeMapping( diff --git a/packages/layers/src/plugins/DataSourcePlugin.ts b/packages/layers/src/plugins/DataSourcePlugin.ts index 44eb96d0a3..b0675ac5ea 100644 --- a/packages/layers/src/plugins/DataSourcePlugin.ts +++ b/packages/layers/src/plugins/DataSourcePlugin.ts @@ -1,6 +1,13 @@ -import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core'; +import { + ILayer, + ILayerPlugin, + ILngLat, + IMapService, + TYPES, +} from '@antv/l7-core'; import Source from '@antv/l7-source'; import { injectable } from 'inversify'; +import { cloneDeep } from 'lodash'; @injectable() export default class DataSourcePlugin implements ILayerPlugin { diff --git a/packages/layers/src/plugins/ShaderUniformPlugin.ts b/packages/layers/src/plugins/ShaderUniformPlugin.ts index c0a7ca9c6c..c8f565b4fe 100644 --- a/packages/layers/src/plugins/ShaderUniformPlugin.ts +++ b/packages/layers/src/plugins/ShaderUniformPlugin.ts @@ -5,6 +5,7 @@ import { ICoordinateSystemService, ILayer, ILayerPlugin, + IMapService, IRendererService, TYPES, } from '@antv/l7-core'; @@ -29,13 +30,28 @@ export default class ShaderUniformPlugin implements ILayerPlugin { @inject(TYPES.IRendererService) private readonly rendererService: IRendererService; + @inject(TYPES.IMapService) + private readonly mapService: IMapService; + public apply(layer: ILayer) { + const version = this.mapService.version; + + let mvp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; // default matrix (for gaode2.x) + // let sceneCenterMKT = [0, 0] layer.hooks.beforeRender.tap('ShaderUniformPlugin', () => { // 重新计算坐标系参数 this.coordinateSystemService.refresh(); + if (version === 'GAODE2.x') { + // @ts-ignore + mvp = this.mapService.map.customCoords.getMVPMatrix(); + // mvp = amapCustomCoords.getMVPMatrix() + // @ts-ignore + // sceneCenterMKT = this.mapService.getCustomCoordCenter() + } + const { width, height } = this.rendererService.getViewportSize(); - layer.models.forEach((model) => + layer.models.forEach((model) => { model.addUniforms({ // 相机参数,包含 VP 矩阵、缩放等级 [CameraUniform.ProjectionMatrix]: this.cameraService.getProjectionMatrix(), @@ -52,13 +68,16 @@ export default class ShaderUniformPlugin implements ILayerPlugin { [CoordinateUniform.PixelsPerDegree]: this.coordinateSystemService.getPixelsPerDegree(), [CoordinateUniform.PixelsPerDegree2]: this.coordinateSystemService.getPixelsPerDegree2(), [CoordinateUniform.PixelsPerMeter]: this.coordinateSystemService.getPixelsPerMeter(), + // 坐标系是高德2.0的时候单独计算 + [CoordinateUniform.Mvp]: mvp, + // u_SceneCenterMKT: sceneCenterMKT, // 其他参数,例如视口大小、DPR 等 u_ViewportSize: [width, height], u_DevicePixelRatio: window.devicePixelRatio, u_ModelMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], u_PickingBuffer: layer.getLayerConfig().pickingBuffer || 0, - }), - ); + }); + }); // TODO:脏检查,决定是否需要渲染 }); diff --git a/packages/layers/src/point/index.ts b/packages/layers/src/point/index.ts index 32226817c5..fb9655337a 100644 --- a/packages/layers/src/point/index.ts +++ b/packages/layers/src/point/index.ts @@ -11,7 +11,6 @@ export default class PointLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new PointModels[modelType](this); - this.models = this.layerModel.initModels(); } public rebuildModels() { diff --git a/packages/layers/src/point/models/fill.ts b/packages/layers/src/point/models/fill.ts index cd47da65f7..3fa71d2493 100644 --- a/packages/layers/src/point/models/fill.ts +++ b/packages/layers/src/point/models/fill.ts @@ -67,7 +67,7 @@ export default class FillModel extends BaseModel { vertexShader: pointFillVert, fragmentShader: pointFillFrag, triangulation: PointFillTriangulation, - depth: { enable: true }, + depth: { enable: false }, blend: this.getBlend(), }), ]; diff --git a/packages/layers/src/point/models/text.ts b/packages/layers/src/point/models/text.ts index 689d0c4f69..07424931a3 100644 --- a/packages/layers/src/point/models/text.ts +++ b/packages/layers/src/point/models/text.ts @@ -330,8 +330,7 @@ export default class TextModel extends BaseModel { } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; const data = this.layer.getEncodedData(); this.glyphInfo = data.map((feature: IEncodeFeature) => { - const { shape = '', coordinates, id, size = 1 } = feature; - + const { shape = '', id, size = 1 } = feature; const shaping = shapeText( shape.toString(), mapping, @@ -345,17 +344,28 @@ export default class TextModel extends BaseModel { const glyphQuads = getGlyphQuads(shaping, textOffset, false); feature.shaping = shaping; feature.glyphQuads = glyphQuads; - feature.centroid = calculteCentroid(coordinates); + // feature.centroid = calculteCentroid(coordinates); + + feature.centroid = calculteCentroid(feature.coordinates); + // if (feature.version === 'GAODE2.x') { + // // 此时地图为高德2.0 + // feature.originCentroid = calculteCentroid(feature.originCoordinates); + // } else { + // // 此时地图不是高德2.0 originCentroid == centroid + // feature.originCentroid = feature.centroid; + // } + feature.originCentroid = feature.version === 'GAODE2.x'?calculteCentroid(feature.originCoordinates):feature.originCentroid = feature.centroid; + this.glyphInfoMap[id as number] = { shaping, glyphQuads, - centroid: calculteCentroid(coordinates), + centroid: calculteCentroid(feature.coordinates), }; return feature; }); } /** - * 文字避让 + * 文字避让 depend on originCentorid */ private filterGlyphs() { const { @@ -374,7 +384,9 @@ export default class TextModel extends BaseModel { const collisionIndex = new CollisionIndex(width, height); const filterData = this.glyphInfo.filter((feature: IEncodeFeature) => { const { shaping, id = 0 } = feature; - const centroid = feature.centroid as [number, number]; + // const centroid = feature.centroid as [number, number]; + // const centroid = feature.originCentroid as [number, number]; + const centroid = (feature.version === 'GAODE2.x'?feature.originCentroid:feature.centroid) as [number, number]; const size = feature.size as number; const fontScale: number = size / 24; const pixels = this.mapService.lngLatToContainer(centroid); diff --git a/packages/layers/src/point/shaders/extrude_vert.glsl b/packages/layers/src/point/shaders/extrude_vert.glsl index ecf797db05..c15eb4d37c 100644 --- a/packages/layers/src/point/shaders/extrude_vert.glsl +++ b/packages/layers/src/point/shaders/extrude_vert.glsl @@ -11,6 +11,7 @@ attribute vec3 a_Size; attribute vec3 a_Normal; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; uniform vec2 u_offsets; varying vec4 v_color; @@ -30,6 +31,12 @@ void main() { float lightWeight = calc_lighting(pos); v_color =vec4(a_Color.rgb * lightWeight, a_Color.w); - gl_Position = project_common_position_to_clipspace(pos); + // gl_Position = project_common_position_to_clipspace(pos); + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * pos; + } else { + gl_Position = project_common_position_to_clipspace(pos); + } setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/point/shaders/fill_vert.glsl b/packages/layers/src/point/shaders/fill_vert.glsl index 4ecb2c2d4c..ff6ff6ed89 100644 --- a/packages/layers/src/point/shaders/fill_vert.glsl +++ b/packages/layers/src/point/shaders/fill_vert.glsl @@ -4,6 +4,7 @@ attribute vec2 a_Extrude; attribute float a_Size; attribute float a_Shape; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; uniform float u_stroke_width : 2; uniform vec2 u_offsets; @@ -16,24 +17,16 @@ varying float v_radius; #pragma include "picking" void main() { + vec2 extrude = a_Extrude; + float shape_type = a_Shape; + float newSize = setPickingSize(a_Size); + // unpack color(vec2) v_color = a_Color; - vec2 extrude = a_Extrude; - - float shape_type = a_Shape; - - float newSize = setPickingSize(a_Size); // radius(16-bit) v_radius = newSize; - vec2 offset = project_pixel(extrude * (newSize + u_stroke_width) + u_offsets); - vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0)); - - - - - // TODO: billboard // anti-alias float antialiasblur = 1.0 / u_DevicePixelRatio / (newSize + u_stroke_width); @@ -41,8 +34,15 @@ void main() { // construct point coords v_data = vec4(extrude, antialiasblur,shape_type); - setPickingColor(a_PickingColor); + vec2 offset = project_pixel(extrude * (newSize + u_stroke_width) + u_offsets); + vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0)); + // gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, project_pixel(setPickingOrder(0.0)), 1.0)); + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * vec4(project_pos.xy + offset, 0.0, 1.0); + } else { gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, project_pixel(setPickingOrder(0.0)), 1.0)); + } + setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/point/shaders/image_vert.glsl b/packages/layers/src/point/shaders/image_vert.glsl index dd55e41724..e4a9b04559 100644 --- a/packages/layers/src/point/shaders/image_vert.glsl +++ b/packages/layers/src/point/shaders/image_vert.glsl @@ -6,6 +6,7 @@ attribute float a_Size; varying vec4 v_color; varying vec2 v_uv; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; uniform float u_stroke_width : 1; uniform vec2 u_offsets; varying float v_size; @@ -19,7 +20,14 @@ void main() { vec4 project_pos = project_position(vec4(a_Position, 1.0)); v_size = a_Size; vec2 offset = project_pixel(u_offsets); - gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy + offset),project_pos.z, 1.0)); + + // gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy + offset),project_pos.z, 1.0)); + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * vec4(vec2(project_pos.xy + offset),project_pos.z, 1.0); + } else { + gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy + offset),project_pos.z, 1.0)); + } gl_PointSize = a_Size * 2.0 * u_DevicePixelRatio; setPickingColor(a_PickingColor); diff --git a/packages/layers/src/point/shaders/normal_vert.glsl b/packages/layers/src/point/shaders/normal_vert.glsl index a721eaa72e..000895e6d1 100644 --- a/packages/layers/src/point/shaders/normal_vert.glsl +++ b/packages/layers/src/point/shaders/normal_vert.glsl @@ -1,6 +1,7 @@ attribute vec3 a_Position; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; attribute float a_Size; attribute vec4 a_Color; varying vec4 v_color; @@ -11,9 +12,18 @@ uniform vec2 u_offsets; #pragma include "picking" void main() { v_color = a_Color; - vec2 offset = project_pixel(u_offsets); - vec4 project_pos = project_position(vec4(a_Position, 1.0)) + vec4(a_Size / 2.,-a_Size /2.,0.,0.); - gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy+offset),project_pos.z,project_pos.w)); + // vec2 offset = project_pixel(u_offsets); + // vec4 project_pos = project_position(vec4(a_Position, 1.0)) + vec4(a_Size / 2.,-a_Size /2.,0.,0.); + // gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy+offset),project_pos.z,project_pos.w));\ + // + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * vec4(a_Position, 1.0); + } else { // else + vec2 offset = project_pixel(u_offsets); + vec4 project_pos = project_position(vec4(a_Position, 1.0)) + vec4(a_Size / 2.,-a_Size /2.,0.,0.); + gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy+offset),project_pos.z,project_pos.w)); + } + gl_PointSize = a_Size * 2.0 * u_DevicePixelRatio; - setPickingColor(a_PickingColor); + setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/point/shaders/text_vert.glsl b/packages/layers/src/point/shaders/text_vert.glsl index 4c279f8bd6..40d00e68a9 100644 --- a/packages/layers/src/point/shaders/text_vert.glsl +++ b/packages/layers/src/point/shaders/text_vert.glsl @@ -10,6 +10,7 @@ attribute float a_Rotate; uniform vec2 u_sdf_map_size; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; varying vec2 v_uv; varying float v_gamma_scale; @@ -25,15 +26,25 @@ void main() { // 文本缩放比例 float fontScale = a_Size / FONT_SIZE; - v_fontScale = fontScale; - vec4 project_pos = project_position(vec4(a_Position, 1.0)); + v_fontScale = fontScale; - vec4 projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); - highp float angle_sin = sin(a_Rotate); - highp float angle_cos = cos(a_Rotate); - mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos); - gl_Position = vec4(projected_position.xy / projected_position.w - + rotation_matrix * a_textOffsets * fontScale / u_ViewportSize * 2.0 * u_DevicePixelRatio, 0.0, 1.0); + vec4 project_pos = project_position(vec4(a_Position, 1.0)); + // vec4 projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + + highp float angle_sin = sin(a_Rotate); + highp float angle_cos = cos(a_Rotate); + mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos); + + // gl_Position = vec4(projected_position.xy / projected_position.w + rotation_matrix * a_textOffsets * fontScale / u_ViewportSize * 2.0 * u_DevicePixelRatio, 0.0, 1.0); + + vec4 projected_position; + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + projected_position = u_Mvp * (vec4(a_Position.xyz, 1.0)); + } else { // else + projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + } + + gl_Position = vec4(projected_position.xy / projected_position.w + rotation_matrix * a_textOffsets * fontScale / u_ViewportSize * 2.0 * u_DevicePixelRatio, 0.0, 1.0); v_gamma_scale = gl_Position.w; setPickingColor(a_PickingColor); diff --git a/packages/layers/src/polygon/shaders/polygon_extrude_vert.glsl b/packages/layers/src/polygon/shaders/polygon_extrude_vert.glsl index f0f0245ed3..715a5c8cf8 100644 --- a/packages/layers/src/polygon/shaders/polygon_extrude_vert.glsl +++ b/packages/layers/src/polygon/shaders/polygon_extrude_vert.glsl @@ -9,6 +9,7 @@ attribute vec3 a_Position; attribute vec3 a_Normal; attribute float a_Size; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; varying vec4 v_Color; @@ -20,7 +21,14 @@ void main() { vec4 pos = vec4(a_Position.xy, a_Position.z * a_Size, 1.0); vec4 project_pos = project_position(pos); - gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + // gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + // gl_Position = u_Mvp * (vec4(project_pos.xyz * vec3(1.0, 1.0, -1.0), 1.0)); + gl_Position = u_Mvp * (vec4(project_pos.xyz, 1.0)); + } else { + gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + } float lightWeight = calc_lighting(pos); // v_Color = a_Color; diff --git a/packages/layers/src/polygon/shaders/polygon_vert.glsl b/packages/layers/src/polygon/shaders/polygon_vert.glsl index 8f83442e9c..1ac57b0e7d 100644 --- a/packages/layers/src/polygon/shaders/polygon_vert.glsl +++ b/packages/layers/src/polygon/shaders/polygon_vert.glsl @@ -3,6 +3,7 @@ attribute vec3 a_Position; attribute vec3 a_Normal; attribute float a_Size; uniform mat4 u_ModelMatrix; +uniform mat4 u_Mvp; varying vec4 v_Color; @@ -12,7 +13,13 @@ varying vec4 v_Color; void main() { v_Color = a_Color; vec4 project_pos = project_position(vec4(a_Position, 1.0)); - gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + // gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + + if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x + gl_Position = u_Mvp * (vec4(project_pos.xyz, 1.0)); + } else { + gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); + } setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/utils/extrude_polyline.ts b/packages/layers/src/utils/extrude_polyline.ts index be92556998..83febd3bc1 100644 --- a/packages/layers/src/utils/extrude_polyline.ts +++ b/packages/layers/src/utils/extrude_polyline.ts @@ -115,6 +115,62 @@ export default class ExtrudePolyline { complex.startIndex = complex.positions.length / 6; return complex; } + public extrude1(points: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1] as vec2; + const cur = points[i] as vec2; + const next = i < points.length - 1 ? points[i + 1] : null; + const amt = this.segment1(complex, count, last, cur, next as vec2); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } + public extrude2(points: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1] as vec2; + const cur = points[i] as vec2; + const next = i < points.length - 1 ? points[i + 1] : null; + const amt = this.segment2(complex, count, last, cur, next as vec2); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } private segment( complex: any, index: number, @@ -329,6 +385,285 @@ export default class ExtrudePolyline { } return count; } + private segment1( + complex: any, + index: number, + last: vec2, + cur: vec2, + next: vec2, + ) { + let count = 0; + const indices = complex.indices; + const positions = complex.positions; + const capSquare = this.cap === 'square'; + const joinBevel = this.join === 'bevel'; + const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; + const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; + direction(lineA, flatCur, flatLast); + let segmentDistance = 0; + if (this.dash) { + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + // if the end cap is type square, we can just push the verts out a bit + if (capSquare) { + // vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness); + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.add(out1, this.normal, lineA); + vec2.add(out2, this.normal, lineA); + + positions.push( + last[0], + last[1], + 0, + this.totalDistance - segmentDistance, + -this.thickness, + 0, + ); + positions.push( + last[0], + last[1], + 0, + this.totalDistance - segmentDistance, + this.thickness, + 0, + ); + } else { + this.extrusionsPosition( + positions, + last, + this.thickness, + this.totalDistance - segmentDistance, + ); + } + } + + indices.push(index + 0, index + 1, index + 2); + + if (!next) { + computeNormal(this.normal, lineA); + if (capSquare) { + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.sub(out2, lineA, this.normal); + vec2.add(out1, lineA, this.normal); + + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness, + 0, + ); + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness, + 0, + ); + } else { + this.extrusionsPosition( + positions, + cur, + this.thickness, + this.totalDistance, + ); + } + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + count += 2; + } else { + const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; + if (isPointEqual(flatCur, flatNext)) { + vec2.add( + flatNext, + flatCur, + vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), + ); + } + direction(lineB, flatNext, flatCur); + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + let bevel = joinBevel; + if (!bevel && this.join === 'miter') { + const limit = miterLen; + if (limit > this.miterLimit) { + bevel = true; + } + } + if (bevel) { + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + -this.thickness * flip, + 0, + ); + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness * flip, + 0, + ); + indices.push( + ...(this.lastFlip !== -flip + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + indices.push(index + 2, index + 3, index + 4); + + computeNormal(tmp, lineB); + vec2.copy(this.normal, tmp); // store normal for next round + + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + -this.thickness * flip, + 0, + ); + count += 3; + } else { + this.extrusionsPosition(positions, cur, miterLen, this.totalDistance); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + flip = -1; + vec2.copy(this.normal, miter); + count += 2; + } + this.lastFlip = flip; + } + return count; + } + private segment2( + complex: any, + index: number, + last: vec2, + cur: vec2, + next: vec2, + ) { + let count = 0; + const normals = complex.normals; + const capSquare = this.cap === 'square'; + const joinBevel = this.join === 'bevel'; + const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; + const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; + direction(lineA, flatCur, flatLast); + let segmentDistance = 0; + if (this.dash) { + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + if (capSquare) { + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.add(out1, this.normal, lineA); + vec2.add(out2, this.normal, lineA); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + } else { + this.extrusionsNormal(normals, this.normal); + } + } + + if (!next) { + computeNormal(this.normal, lineA); + if (capSquare) { + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.sub(out2, lineA, this.normal); + vec2.add(out1, lineA, this.normal); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + } else { + this.extrusionsNormal(normals, this.normal); + } + + count += 2; + } else { + const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; + if (isPointEqual(flatCur, flatNext)) { + vec2.add( + flatNext, + flatCur, + vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), + ); + } + direction(lineB, flatNext, flatCur); + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + let bevel = joinBevel; + if (!bevel && this.join === 'miter') { + const limit = miterLen; + if (limit > this.miterLimit) { + bevel = true; + } + } + + if (bevel) { + normals.push(this.normal[0], this.normal[1], 0); + normals.push(miter[0], miter[1], 0); + + computeNormal(tmp, lineB); + vec2.copy(this.normal, tmp); // store normal for next round + normals.push(this.normal[0], this.normal[1], 0); + + count += 3; + } else { + this.extrusionsNormal(normals, miter); + flip = -1; + vec2.copy(this.normal, miter); + count += 2; + } + this.lastFlip = flip; + } + return count; + } private extrusions( positions: number[], @@ -343,6 +678,20 @@ export default class ExtrudePolyline { positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0); positions.push(point[0], point[1], 0, distanceRadio, thickness, 0); } + private extrusionsPosition( + positions: number[], + point: vec2, // 顶点 + thickness: number, // 高度 + distanceRadio: number, + ) { + positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0); + positions.push(point[0], point[1], 0, distanceRadio, thickness, 0); + } + private extrusionsNormal(normals: number[], normal: vec2) { + // 法向量 + normals.push(normal[0], normal[1], 0); + normals.push(normal[0], normal[1], 0); + } private lineSegmentDistance(b1: vec2, a1: vec2) { const dx = a1[0] - b1[0]; const dy = a1[1] - b1[1]; diff --git a/packages/maps/src/amap/map.ts b/packages/maps/src/amap/map.ts index 76acb99243..3055c07131 100644 --- a/packages/maps/src/amap/map.ts +++ b/packages/maps/src/amap/map.ts @@ -25,6 +25,7 @@ import { mat4, vec2, vec3 } from 'gl-matrix'; import { inject, injectable } from 'inversify'; import { IAMapEvent, IAMapInstance } from '../../typings/index'; import { toPaddingOptions } from '../utils'; +import { Version } from '../version'; import './logo.css'; import { MapTheme } from './theme'; import Viewport from './Viewport'; @@ -54,6 +55,7 @@ const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; // 暂时关闭 fix 统一不同坐标 @injectable() export default class AMapService implements IMapService { + public version: string = Version['GAODE1.x']; /** * 原始地图实例 */ @@ -328,7 +330,7 @@ export default class AMapService } = this.config; // 高德地图创建独立的container; // tslint:disable-next-line:typedef - await new Promise((resolve) => { + await new Promise((resolve) => { const resolveMap = () => { if (mapInstance) { this.map = mapInstance as AMap.Map & IAMapInstance; @@ -458,7 +460,6 @@ export default class AMapService offsetOrigin: [position.x, position.y], }); const { offsetZoom = LNGLAT_OFFSET_ZOOM_THRESHOLD } = this.config; - // set coordinate system if (this.viewport.getZoom() > offsetZoom) { this.coordinateSystemService.setCoordinateSystem( diff --git a/packages/maps/src/amap2/Viewport.ts b/packages/maps/src/amap2/Viewport.ts new file mode 100644 index 0000000000..63fc246759 --- /dev/null +++ b/packages/maps/src/amap2/Viewport.ts @@ -0,0 +1,124 @@ +import { IMapCamera, IViewport } from '@antv/l7-core'; +import { mat4, vec3 } from 'gl-matrix'; + +export default class Viewport implements IViewport { + private projectionMatrix: mat4 = mat4.create(); + private viewMatrix: mat4 = mat4.create(); + private viewProjectionMatrix: mat4 = mat4.create(); + private ViewProjectionMatrixUncentered: mat4 = mat4.create(); + private viewUncenteredMatrix: mat4 = mat4.create(); + private zoom: number; + private center: number[]; + + public syncWithMapCamera(mapCamera: Partial) { + const { + zoom = 1, + center = [0, 0], + offsetOrigin = [0, 0], + cameraPosition = [0, 0, 0], + up = [0, 1, 0], + lookAt = [0, 0, 0], + aspect = 1, + near = 0.1, + far = 1000, + fov = 0, + } = mapCamera; + this.zoom = zoom; + this.center = center; + + // 计算透视投影矩阵 projectionMatrix + mat4.perspective(this.projectionMatrix, fov, aspect, near, far); + + // 计算相机矩阵 viewMatrix + const eyePoint = vec3.fromValues(...cameraPosition); + const lookAtPoint = vec3.fromValues(...lookAt); + const upDirect = vec3.fromValues(...up); + mat4.lookAt(this.viewMatrix, eyePoint, lookAtPoint, upDirect); + + this.viewUncenteredMatrix = mat4.clone(this.viewMatrix); + + // 移动相机位置 + mat4.translate( + this.viewMatrix, + this.viewMatrix, + vec3.fromValues(-offsetOrigin[0], offsetOrigin[1], 0), + ); + + mat4.multiply( + this.viewProjectionMatrix, + this.projectionMatrix, + this.viewMatrix, + ); + mat4.multiply( + this.ViewProjectionMatrixUncentered, + this.projectionMatrix, + this.viewMatrix, + ); + } + + public getZoom(): number { + return this.zoom; + } + + public getZoomScale(): number { + // 512 尺寸下的缩放:2 ^ 19 + return 524288; + } + + public getCenter(): [number, number] { + const [lng, lat] = this.center; + return [lng, lat]; + } + + public getProjectionMatrix(): number[] { + // @ts-ignore + return this.projectionMatrix; + } + + public getViewMatrix(): number[] { + // @ts-ignore + return this.viewMatrix; + } + + public getViewMatrixUncentered(): number[] { + // @ts-ignore + return this.viewUncenteredMatrix; + } + public getViewProjectionMatrix(): number[] { + // @ts-ignore + return this.viewProjectionMatrix; + } + + public getViewProjectionMatrixUncentered(): number[] { + // @ts-ignore + return this.ViewProjectionMatrixUncentered; + } + + public getFocalDistance() { + return 1; + } + + /** + * P20 坐标系,固定 scale + */ + public projectFlat( + lngLat: [number, number], + scale?: number | undefined, + ): [number, number] { + const maxs = 85.0511287798; + const lat = Math.max(Math.min(maxs, lngLat[1]), -maxs); + // tslint:disable-next-line:no-bitwise + const zoomScale = 256 << 20; + let d = Math.PI / 180; + let x = lngLat[0] * d; + let y = lat * d; + y = Math.log(Math.tan(Math.PI / 4 + y / 2)); + const a = 0.5 / Math.PI; + const b = 0.5; + const c = -0.5 / Math.PI; + d = 0.5; + x = zoomScale * (a * x + b) - 215440491; + y = -(zoomScale * (c * y + d) - 106744817); + return [x, y]; + } +} diff --git a/packages/maps/src/amap2/index.ts b/packages/maps/src/amap2/index.ts new file mode 100644 index 0000000000..1661938a64 --- /dev/null +++ b/packages/maps/src/amap2/index.ts @@ -0,0 +1,11 @@ +import { IAMapInstance } from '../../typings/index'; +import BaseMapWrapper from '../BaseMapWrapper'; +import AMapService from './map'; + +export default class AMapWrapper2 extends BaseMapWrapper< + AMap.Map & IAMapInstance +> { + protected getServiceConstructor() { + return AMapService; + } +} diff --git a/packages/maps/src/amap2/logo.css b/packages/maps/src/amap2/logo.css new file mode 100644 index 0000000000..5dbe1028c9 --- /dev/null +++ b/packages/maps/src/amap2/logo.css @@ -0,0 +1,3 @@ +.amap-logo{ + display: none !important; +} diff --git a/packages/maps/src/amap2/map.ts b/packages/maps/src/amap2/map.ts new file mode 100644 index 0000000000..83b1822463 --- /dev/null +++ b/packages/maps/src/amap2/map.ts @@ -0,0 +1,625 @@ +/** + * AMapService + */ +import AMapLoader from '@amap/amap-jsapi-loader'; +import { + Bounds, + CoordinateSystem, + ICameraOptions, + ICoordinateSystemService, + IGlobalConfigService, + ILngLat, + ILogService, + IMapConfig, + IMapService, + IMercator, + IPoint, + IStatusOptions, + IViewport, + MapServiceEvent, + MapStyle, + Point, + TYPES, +} from '@antv/l7-core'; +import { DOM } from '@antv/l7-utils'; +import { mat4, vec2, vec3 } from 'gl-matrix'; +import { inject, injectable } from 'inversify'; +import { IAMapEvent, IAMapInstance } from '../../typings/index'; +import { toPaddingOptions } from '../utils'; +import { Version } from '../version'; +import './logo.css'; +import { MapTheme } from './theme'; +import Viewport from './Viewport'; + +let mapdivCount = 0; +// @ts-ignore +window.forceWebGL = true; + +// const AMAP_API_KEY: string = '15cd8a57710d40c9b7c0e3cc120f1200'; +const AMAP_API_KEY: string = 'ff533602d57df6f8ab3b0fea226ae52f'; +// const AMAP_VERSION: string = '1.4.15'; +const AMAP_VERSION: string = '2.0'; +/** + * 确保多个场景只引入一个高德地图脚本 + */ +const AMAP_SCRIPT_ID: string = 'amap-script'; +/** + * 高德地图脚本是否加载完毕 + */ +let amapLoaded = false; +/** + * 高德地图脚本加载成功等待队列,成功之后依次触发 + */ +let pendingResolveQueue: Array<() => void> = []; + +/** + * AMapService + */ +@injectable() +export default class AMapService + implements IMapService { + public version: string = Version['GAODE2.x']; + /** + * 原始地图实例 + */ + public map: AMap.Map & IAMapInstance; + + /** + * 用于 customCooords 数据的计算 + */ + public sceneCenter!: [number, number]; // 一般使用用户数据的第一个 + public sceneCenterMKT!: [number, number]; // 莫卡托 + + @inject(TYPES.IGlobalConfigService) + private readonly configService: IGlobalConfigService; + + @inject(TYPES.ILogService) + private readonly logger: ILogService; + + @inject(TYPES.MapConfig) + private readonly config: Partial; + + @inject(TYPES.ICoordinateSystemService) + private readonly coordinateSystemService: ICoordinateSystemService; + + @inject(TYPES.IEventEmitter) + private eventEmitter: any; + + private markerContainer: HTMLElement; + private $mapContainer: HTMLElement | null; + + private viewport: Viewport; + + private cameraChangedCallback: (viewport: IViewport) => void; + + /** + * 设置数据的绘制中心 高德2.0 + */ + public setCustomCoordCenter(center: [number, number]) { + this.sceneCenter = center; + // @ts-ignore + this.sceneCenterMKT = this.map.getProjection().project(...this.sceneCenter); + } + + public getCustomCoordCenter(): [number, number] { + return this.sceneCenterMKT; + } + /** + * 根据数据的绘制中心转换经纬度数据 高德2.0 + */ + public lngLatToCoord(lnglat: [number, number]) { + // @ts-ignore + const proj = this.map.getProjection(); + const project = proj.project; + // console.log('proj', 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); + } + + /** + * 转化线、面类型的点位数据 + */ + // public lngLatToCoords(lnglatArray: Array> | Array<[number, number]>): Array>|Array<[number, number]> { + public lngLatToCoords( + lnglatArray: number[][][] | number[][], + ): number[][][] | number[][] { + // @ts-ignore + return lnglatArray.map((lnglats) => { + if (typeof lnglats[0] === 'number') { + return this.lngLatToCoord(lnglats); + } else { + // @ts-ignore + return lnglats.map((lnglat) => { + return this.lngLatToCoord(lnglat); + }); + } + }); + } + + public addMarkerContainer(): void { + const mapContainer = this.map.getContainer(); + if (mapContainer !== null) { + const amap = mapContainer.getElementsByClassName( + 'amap-maps', + )[0] as HTMLElement; + this.markerContainer = DOM.create('div', 'l7-marker-container', amap); + } + } + public getMarkerContainer(): HTMLElement { + return this.markerContainer; + } + + // map event + public on(type: string, handler: (...args: any[]) => void): void { + if (MapServiceEvent.indexOf(type) !== -1) { + this.eventEmitter.on(type, handler); + } else { + this.map.on(type, handler); + } + } + public off(type: string, handler: (...args: any[]) => void): void { + if (MapServiceEvent.indexOf(type) !== -1) { + this.eventEmitter.off(type, handler); + } else { + this.map.off(type, handler); + } + } + + public getContainer(): HTMLElement | null { + return this.map.getContainer(); + } + + public getMapCanvasContainer(): HTMLElement { + return this.map + .getContainer() + ?.getElementsByClassName('amap-maps')[0] as HTMLElement; + } + + public getSize(): [number, number] { + const size = this.map.getSize(); + return [size.getWidth(), size.getHeight()]; + } + + public getType() { + return 'amap'; + } + public getZoom(): number { + // 统一返回 Mapbox 缩放等级 + return this.map.getZoom() - 1; + } + + public setZoom(zoom: number): void { + return this.map.setZoom(zoom); + } + + public getCenter(options?: ICameraOptions): ILngLat { + if (options?.padding) { + const originCenter = this.getCenter(); + const [w, h] = this.getSize(); + const padding = toPaddingOptions(options.padding); + const px = this.lngLatToPixel([originCenter.lng, originCenter.lat]); + const offsetPx = [ + (padding.right - padding.left) / 2, + (padding.bottom - padding.top) / 2, + ]; + + const newCenter = this.pixelToLngLat([ + px.x - offsetPx[0], + px.y - offsetPx[1], + ]); + return newCenter; + } + const center = this.map.getCenter(); + return { + lng: center.getLng(), + lat: center.getLat(), + }; + } + public setCenter(lnglat: [number, number], options?: ICameraOptions): void { + if (options?.padding) { + const padding = toPaddingOptions(options.padding); + const px = this.lngLatToPixel(lnglat); + const offsetPx = [ + (padding.right - padding.left) / 2, + (padding.bottom - padding.top) / 2, + ]; + const newCenter = this.pixelToLngLat([ + px.x + offsetPx[0], + px.y + offsetPx[1], + ]); + this.map.setCenter([newCenter.lng, newCenter.lat]); + } else { + this.map.setCenter(lnglat); + } + } + public getPitch(): number { + return this.map.getPitch(); + } + + public getRotation(): number { + // 统一返回逆时针旋转角度 + return 360 - this.map.getRotation(); + } + + public getBounds(): Bounds { + // @ts-ignore + // const amapBound = this.map.getBounds().toBounds(); + // const NE = amapBound.getNorthEast(); + // const SW = amapBound.getSouthWest(); + const bounds = this.map.getBounds(); + // console.log('bounds', bounds) + + // @ts-ignore + const NE = bounds.getNorthEast(); + // @ts-ignore + const SW = bounds.getSouthWest(); + const center = this.getCenter(); + const maxlng = + center.lng > NE.getLng() || center.lng < SW.getLng() + ? 180 - NE.getLng() + : NE.getLng(); + const minlng = center.lng < SW.getLng() ? SW.getLng() - 180 : SW.getLng(); + // 兼容 Mapbox,统一返回西南、东北 + return [ + [minlng, SW.getLat()], + [maxlng, NE.getLat()], + ]; + } + + public getMinZoom(): number { + const zooms = this.map.get('zooms') as [number, number]; + return zooms[0] - 1; + } + public getMaxZoom(): number { + const zooms = this.map.get('zooms') as [number, number]; + return zooms[1] - 1; + } + public setRotation(rotation: number): void { + return this.map.setRotation(rotation); + } + + public setPitch(pitch: number) { + return this.map.setPitch(pitch); + } + public zoomIn(): void { + this.map.zoomIn(); + } + + public zoomOut(): void { + this.map.zoomOut(); + } + + public panTo(p: [number, number]): void { + this.map.panTo(p); + } + public panBy(pixel: [number, number]): void { + this.map.panTo(pixel); + } + public fitBounds(extent: Bounds): void { + this.map.setBounds( + new AMap.Bounds([extent[0][0], extent[0][1], extent[1][0], extent[1][1]]), + ); + } + public setZoomAndCenter(zoom: number, center: [number, number]): void { + this.map.setZoomAndCenter(zoom, center); + } + public setMapStyle(style: string): void { + this.map.setMapStyle(this.getMapStyle(style)); + } + + public setMapStatus(option: Partial): void { + this.map.setStatus(option); + } + public pixelToLngLat(pixel: [number, number]): ILngLat { + const lngLat = this.map.pixelToLngLat(new AMap.Pixel(pixel[0], pixel[1])); + return { lng: lngLat.getLng(), lat: lngLat.getLat() }; + } + public lngLatToPixel(lnglat: [number, number]): IPoint { + const p = this.map.lnglatToPixel(new AMap.LngLat(lnglat[0], lnglat[1])); + return { + x: p.getX(), + y: p.getY(), + }; + } + public containerToLngLat(pixel: [number, number]): ILngLat { + const ll = new AMap.Pixel(pixel[0], pixel[1]); + const lngLat = this.map.containerToLngLat(ll); + return { + lng: lngLat?.getLng(), + lat: lngLat?.getLat(), + }; + } + public lngLatToContainer(lnglat: [number, number]): IPoint { + const ll = new AMap.LngLat(lnglat[0], lnglat[1]); + const pixel = this.map.lngLatToContainer(ll); + return { + x: pixel.getX(), + y: pixel.getY(), + }; + } + + public lngLatToMercator( + lnglat: [number, number], + altitude: number, + ): IMercator { + return { + x: 0, + y: 0, + z: 0, + }; + } + + public getModelMatrix( + lnglat: [number, number], + altitude: number, + rotate: [number, number, number], + scale: [number, number, number] = [1, 1, 1], + origin: IMercator = { x: 0, y: 0, z: 0 }, + ): number[] { + const flat = this.viewport.projectFlat(lnglat); + // @ts-ignore + const modelMatrix = mat4.create(); + + mat4.translate( + modelMatrix, + modelMatrix, + vec3.fromValues(flat[0], flat[1], altitude), + ); + mat4.scale( + modelMatrix, + modelMatrix, + vec3.fromValues(scale[0], scale[1], scale[2]), + ); + + mat4.rotateX(modelMatrix, modelMatrix, rotate[0]); + mat4.rotateY(modelMatrix, modelMatrix, rotate[1]); + mat4.rotateZ(modelMatrix, modelMatrix, rotate[2]); + + return (modelMatrix as unknown) as number[]; + } + public async init(): Promise { + const { + id, + style = 'light', + minZoom = 0, + maxZoom = 18, + token = AMAP_API_KEY, + mapInstance, + plugin = [], + ...rest + } = this.config; + // 高德地图创建独立的container; + + // tslint:disable-next-line:typedef + await new Promise((resolve) => { + const resolveMap = () => { + if (mapInstance) { + this.map = mapInstance as AMap.Map & IAMapInstance; + this.$mapContainer = this.map.getContainer(); + + setTimeout(() => { + this.map.on('viewchange', this.handleViewChanged); + resolve(); + }, 30); + } else { + this.$mapContainer = this.creatAmapContainer( + id as string | HTMLDivElement, + ); + + const map = new AMap.Map(this.$mapContainer, { + mapStyle: this.getMapStyle(style as string), + zooms: [minZoom, maxZoom], + viewMode: '3D', + ...rest, + }); + // @ts-ignore + this.map = map; + + // 在使用 map.customCoords 的时候必须使用 + const mapInitCenter = map.getCenter(); + // @ts-ignore + map.customCoords.setCenter([mapInitCenter.lng, mapInitCenter.lat]); + + // @ts-ignore + this.setCustomCoordCenter([mapInitCenter.lng, mapInitCenter.lat]); + // 监听地图相机事件 + map.on('viewchange', this.handleViewChanged); + + setTimeout(() => { + resolve(); + }, 10); + } + }; + this.viewport = new Viewport(); + if (!amapLoaded && !mapInstance) { + if (token === AMAP_API_KEY) { + this.logger.warn(this.configService.getSceneWarninfo('MapToken')); + } + amapLoaded = true; + plugin.push('Map3D'); + AMapLoader.load({ + key: token, // 申请好的Web端开发者Key,首次调用 load 时必填 + version: AMAP_VERSION, // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 + plugins: plugin, // 需要使用的的插件列表,如比例尺'AMap.Scale'等 + }) + .then((AMap) => { + resolveMap(); + if (pendingResolveQueue.length) { + pendingResolveQueue.forEach((r) => r()); + pendingResolveQueue = []; + } + }) + .catch((e) => { + throw new Error(e); + }); + } else { + if ((amapLoaded && window.AMap) || mapInstance) { + resolveMap(); + } else { + pendingResolveQueue.push(resolveMap); + } + } + }); + } + + public exportMap(type: 'jpg' | 'png'): string { + const renderCanvas = this.getContainer()?.getElementsByClassName( + 'amap-layer', + )[0] as HTMLCanvasElement; + const layersPng = + type === 'jpg' + ? (renderCanvas?.toDataURL('image/jpeg') as string) + : (renderCanvas?.toDataURL('image/png') as string); + return layersPng; + } + + public emit(name: string, ...args: any[]) { + this.eventEmitter.emit(name, ...args); + } + + public once(name: string, ...args: any[]) { + this.eventEmitter.once(name, ...args); + } + + public destroy() { + this.map.destroy(); + // @ts-ignore + delete window.initAMap; + const $jsapi = document.getElementById(AMAP_SCRIPT_ID); + if ($jsapi) { + document.head.removeChild($jsapi); + } + } + + public getMapContainer() { + return this.$mapContainer; + } + + public onCameraChanged(callback: (viewport: IViewport) => void): void { + this.cameraChangedCallback = callback; + } + + public initViewPort() { + // @ts-ignore + const { + // @ts-ignore + fov, + // @ts-ignore + near, + // @ts-ignore + far, + // @ts-ignore + aspect, + // @ts-ignore + position, + // @ts-ignore + lookAt, + // @ts-ignore + up, + // @ts-ignore + } = this.map.customCoords.getCameraParams(); + const center = this.map.getCenter(); + const zoom = this.map.getZoom(); + + if (this.cameraChangedCallback) { + this.viewport.syncWithMapCamera({ + aspect, + far, + fov, + cameraPosition: position, + lookAt, + near, + up, + // AMap 定义的缩放等级 与 Mapbox 相差 1 + zoom: zoom - 1, // 与amap1.x对比相差一个级别 + center: [center.getLat(), center.getLng()], + offsetOrigin: [position[0], position[1]], + }); + + // set coordinate system + this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20_2); + this.cameraChangedCallback(this.viewport); + } + } + + private _sub(a: number[] | vec3 | vec2, b: number[]): [number, number] { + const r: [number, number] = [0, 0]; + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + return r; + } + + /** + * + * @param e + */ + private handleViewChanged = (e: any): void => { + // @ts-ignore + const { + // @ts-ignore + fov, + // @ts-ignore + near, + // @ts-ignore + far, + // @ts-ignore + aspect, + // @ts-ignore + position, + // @ts-ignore + lookAt, + // @ts-ignore + up, + // @ts-ignore + } = this.map.customCoords.getCameraParams(); + const { zoom } = e; + // console.log('zoom', zoom, this.map.getZoom()) + const center = this.map.getCenter(); + if (this.cameraChangedCallback) { + // resync viewport + this.viewport.syncWithMapCamera({ + aspect, + far, + fov, + cameraPosition: position, + lookAt, + up, + near, + // AMap 定义的缩放等级 与 Mapbox 相差 1 + zoom: zoom - 1, // 与amap1.x对比相差一个级别 + center: [center.getLat(), center.getLng()], + offsetOrigin: [position[0], position[1]], + }); + + // set coordinate system + this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20_2); + this.cameraChangedCallback(this.viewport); + } + }; + + private getMapStyle(name: string): string { + return MapTheme[name] ? MapTheme[name] : name; + } + + private creatAmapContainer(id: string | HTMLDivElement) { + let $wrapper = id as HTMLDivElement; + if (typeof id === 'string') { + $wrapper = document.getElementById(id) as HTMLDivElement; + } + const $amapdiv = document.createElement('div'); + $amapdiv.style.cssText += ` + position: absolute; + top: 0; + height: 100%; + width: 100%; + `; + $amapdiv.id = 'l7_amap_div' + mapdivCount++; + $wrapper.appendChild($amapdiv); + return $amapdiv; + } +} diff --git a/packages/maps/src/amap2/theme.ts b/packages/maps/src/amap2/theme.ts new file mode 100644 index 0000000000..d7654ddafc --- /dev/null +++ b/packages/maps/src/amap2/theme.ts @@ -0,0 +1,8 @@ +export const MapTheme: { + [key: string]: any; +} = { + dark: 'amap://styles/2a09079c3daac9420ee53b67307a8006?isPublic=true', + light: 'amap://styles/1fd9f8ef9751298f11f5c56968312c70?isPublic=true', + normal: 'amap://styles/normal', + blank: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true', +}; diff --git a/packages/maps/src/index.ts b/packages/maps/src/index.ts index 7e363b9af7..c3e1da15fc 100644 --- a/packages/maps/src/index.ts +++ b/packages/maps/src/index.ts @@ -1,5 +1,6 @@ import GaodeMap from './amap/'; +import GaodeMap2 from './amap2/'; import Map from './map/'; import Mapbox from './mapbox/'; -export { GaodeMap, Mapbox, Map }; +export { GaodeMap, GaodeMap2, Mapbox, Map }; diff --git a/packages/maps/src/map/map.ts b/packages/maps/src/map/map.ts index 32bb5b95d2..e8160a556c 100644 --- a/packages/maps/src/map/map.ts +++ b/packages/maps/src/map/map.ts @@ -22,7 +22,7 @@ import { Map } from '@antv/l7-map'; import { DOM } from '@antv/l7-utils'; import { mat4, vec2, vec3 } from 'gl-matrix'; import { inject, injectable } from 'inversify'; - +import { Version } from '../version'; import Viewport from './Viewport'; const EventMap: { [key: string]: any; @@ -40,6 +40,7 @@ const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; */ @injectable() export default class L7MapService implements IMapService { + public version: string = Version.L7MAP; public map: Map; @inject(TYPES.MapConfig) diff --git a/packages/maps/src/mapbox/map.ts b/packages/maps/src/mapbox/map.ts index 46a545c35c..01d96e39c2 100644 --- a/packages/maps/src/mapbox/map.ts +++ b/packages/maps/src/mapbox/map.ts @@ -22,10 +22,10 @@ import { DOM } from '@antv/l7-utils'; import { mat4, vec2, vec3 } from 'gl-matrix'; import { inject, injectable } from 'inversify'; import mapboxgl, { IControl, Map } from 'mapbox-gl'; - // tslint:disable-next-line:no-submodule-imports import 'mapbox-gl/dist/mapbox-gl.css'; import { IMapboxInstance } from '../../typings/index'; +import { Version } from '../version'; import Viewport from './Viewport'; window.mapboxgl = mapboxgl; const EventMap: { @@ -47,6 +47,7 @@ const MAPBOX_API_KEY = @injectable() export default class MapboxService implements IMapService { + public version: string = Version.MAPBOX; public map: Map & IMapboxInstance; @inject(TYPES.MapConfig) diff --git a/packages/maps/src/version.ts b/packages/maps/src/version.ts new file mode 100644 index 0000000000..66006cf1a3 --- /dev/null +++ b/packages/maps/src/version.ts @@ -0,0 +1,9 @@ +/** + * 当前 L7 内部存在的地图版本 + */ +export enum Version { + 'GAODE1.x' = 'GAODE1.x', + 'GAODE2.x' = 'GAODE2.x', + 'MAPBOX' = 'MAPBOX', + 'L7MAP' = 'L7MAP', +} diff --git a/packages/maps/typings/index.d.ts b/packages/maps/typings/index.d.ts index ac3796c393..a74363a13e 100644 --- a/packages/maps/typings/index.d.ts +++ b/packages/maps/typings/index.d.ts @@ -17,8 +17,15 @@ interface IAMapEvent { }; } +interface CustomCoords { + getCameraParams(): void; + getCenter(): void; + getMVPMatrix(): void; + [other:string]:any +} interface IAMapInstance { get(key: string): unknown; + customCoords?: CustomCoords; } interface IMapboxInstance { diff --git a/packages/source/src/source.ts b/packages/source/src/source.ts index ab2bc5cd06..c647cf18ec 100644 --- a/packages/source/src/source.ts +++ b/packages/source/src/source.ts @@ -28,6 +28,7 @@ import { getParser, getTransform } from './'; import { cluster } from './transform/cluster'; import { statMap } from './utils/statistics'; import { getColumn } from './utils/util'; + function mergeCustomizer(objValue: any, srcValue: any) { if (Array.isArray(srcValue)) { return srcValue; @@ -54,6 +55,7 @@ export default class Source extends EventEmitter { zoom: -99, method: 'count', }; + private readonly mapService: IMapService; // 原始数据 private originData: any; @@ -66,7 +68,6 @@ export default class Source extends EventEmitter { super(); // this.rawData = cloneDeep(data); this.originData = data; - this.initCfg(cfg); this.hooks.init.tap('parser', () => { @@ -204,6 +205,7 @@ export default class Source extends EventEmitter { const trans = this.transforms; trans.forEach((tran: ITransform) => { const { type } = tran; + const data = getTransform(type)(this.data, tran); Object.assign(this.data, data); }); diff --git a/stories/Map/components/amap2demo.tsx b/stories/Map/components/amap2demo.tsx new file mode 100644 index 0000000000..656583d601 --- /dev/null +++ b/stories/Map/components/amap2demo.tsx @@ -0,0 +1,88 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +export default class Amap2demo extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + center: [121.107846, 30.267069], + pitch: 0, + style: 'normal', + zoom: 13, + animateEnable: false, + }), + }); + let originData = [ + { + lng: 121.107846, + lat: 30.267069, + }, + { + lng: 121.1, + lat: 30.267069, + }, + { + lng: 120.107846, + lat: 30.267069, + }, + { + lng: 38.54, + lat: 77.02, + }, + ]; + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + + const layer = new PointLayer() + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('circle') + // .shape('normal') + .color('rgba(255, 0, 0, 0.9)') + .size(10) + .style({ + stroke: '#fff', + storkeWidth: 2, + }) + .active(true); + scene.addLayer(layer); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_arcLine.tsx b/stories/Map/components/amap2demo_arcLine.tsx new file mode 100644 index 0000000000..412464cbde --- /dev/null +++ b/stories/Map/components/amap2demo_arcLine.tsx @@ -0,0 +1,74 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +export default class Amap2demo_arcLine extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + pitch: 0, + center: [107.77791556935472, 35.443286920228644], + zoom: 2.9142882493605033, + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', + ) + .then((res) => res.text()) + .then((data) => { + const layer = new LineLayer({}) + .source(data, { + parser: { + type: 'csv', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(1) + .shape('arc') + .color('#8C1EB2') + .style({ + opacity: 0.8, + blur: 0.99, + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_extrude.tsx b/stories/Map/components/amap2demo_extrude.tsx new file mode 100644 index 0000000000..5e81f39a66 --- /dev/null +++ b/stories/Map/components/amap2demo_extrude.tsx @@ -0,0 +1,84 @@ +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amapdemo_extrude extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + center: [121.107846, 30.267069], + pitch: 35.210526315789465, + style: 'normal', + zoom: 8, + animateEnable: false, + }), + }); + + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('cylinder') + .size('t', function(level) { + return [1, 2, level * 2 + 20]; + }) + .active(true) + .color('t', [ + '#094D4A', + '#146968', + '#1D7F7E', + '#289899', + '#34B6B7', + '#4AC5AF', + '#5FD3A6', + '#7BE39E', + '#A1EDB8', + '#CEF8D6', + ]) + .style({ + opacity: 1.0, + }); + scene.addLayer(pointLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_image.tsx b/stories/Map/components/amap2demo_image.tsx new file mode 100644 index 0000000000..f89d4402d4 --- /dev/null +++ b/stories/Map/components/amap2demo_image.tsx @@ -0,0 +1,80 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +export default class Amap2demo_image extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + pitch: 0, + style: 'light', + center: [121.434765, 31.256735], + zoom: 14.83, + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json', + ) + .then((res) => res.json()) + .then((data) => { + scene.addImage( + '00', + 'https://gw.alipayobjects.com/zos/basement_prod/604b5e7f-309e-40db-b95b-4fac746c5153.svg', + ); + scene.addImage( + '01', + 'https://gw.alipayobjects.com/zos/basement_prod/30580bc9-506f-4438-8c1a-744e082054ec.svg', + ); + scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/basement_prod/7aa1f460-9f9f-499f-afdf-13424aa26bbf.svg', + ); + const imageLayer = new PointLayer() + .source(data, { + parser: { + type: 'json', + x: 'longitude', + y: 'latitude', + }, + }) + .shape('name', ['00', '01', '02']) + .size(20); + scene.addLayer(imageLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_polygon.tsx b/stories/Map/components/amap2demo_polygon.tsx new file mode 100644 index 0000000000..b58648acd8 --- /dev/null +++ b/stories/Map/components/amap2demo_polygon.tsx @@ -0,0 +1,140 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { DrawPolygon } from '@antv/l7-draw'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +function convertRGB2Hex(rgb: number[]) { + return ( + '#' + rgb.map((r) => ('0' + Math.floor(r).toString(16)).slice(-2)).join('') + ); +} + +export default class Amap2demo_polygon extends React.Component { + private gui: dat.GUI; + private $stats: Node; + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const response = await fetch( + // 'https://gw.alipayobjects.com/os/basement_prod/f79485d8-d86f-4bb3-856d-537b586be06e.json', + 'https://gw.alipayobjects.com/os/basement_prod/619a6f16-ecb0-4fca-9f9a-b06b67f6f02b.json', + ); + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + pitch: 0, + // style: 'dark', + center: [-44.40673828125, -18.375379094031825], + zoom: 13, + }), + }); + this.scene = scene; + const data = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [110.5224609375, 32.731840896865684], + [113.0712890625, 32.731840896865684], + [113.0712890625, 34.56085936708384], + [110.5224609375, 34.56085936708384], + [110.5224609375, 32.731840896865684], + ], + [ + [111.26953125, 33.52307880890422], + [111.26953125, 34.03445260967645], + [112.03857421875, 34.03445260967645], + [112.03857421875, 33.52307880890422], + [111.26953125, 33.52307880890422], + ], + ], + [ + [ + [115.04882812499999, 34.379712580462204], + [114.9609375, 33.46810795527896], + [115.8837890625, 33.50475906922609], + [115.86181640625001, 34.379712580462204], + [115.04882812499999, 34.379712580462204], + ], + ], + ], + }, + }, + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [113.8623046875, 30.031055426540206], + [116.3232421875, 30.031055426540206], + [116.3232421875, 31.090574094954192], + [113.8623046875, 31.090574094954192], + [113.8623046875, 30.031055426540206], + ], + [ + [117.26806640625, 32.13840869677249], + [118.36669921875, 32.13840869677249], + [118.36669921875, 32.47269502206151], + [117.26806640625, 32.47269502206151], + [117.26806640625, 32.13840869677249], + ], + ], + }, + }, + ], + }; + + const layer = new PolygonLayer({ + autoFit: true, + }) + .source(data) + .shape('fill') + .color('red') + .style({ + opacity: 1.0, + }); + scene.addLayer(layer); + + const layer2 = new PolygonLayer({ + autoFit: true, + }) + .source(data) + .shape('line') + .color('#000') + .style({ + opacity: 1.0, + }); + scene.addLayer(layer2); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/Map/components/amap2demo_polygon_extrude.tsx b/stories/Map/components/amap2demo_polygon_extrude.tsx new file mode 100644 index 0000000000..3ef4ea5230 --- /dev/null +++ b/stories/Map/components/amap2demo_polygon_extrude.tsx @@ -0,0 +1,132 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { DrawPolygon } from '@antv/l7-draw'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +function convertRGB2Hex(rgb: number[]) { + return ( + '#' + rgb.map((r) => ('0' + Math.floor(r).toString(16)).slice(-2)).join('') + ); +} + +export default class Amap2demo_polygon_extrude extends React.Component { + private gui: dat.GUI; + private $stats: Node; + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const response = await fetch( + // 'https://gw.alipayobjects.com/os/basement_prod/f79485d8-d86f-4bb3-856d-537b586be06e.json', + 'https://gw.alipayobjects.com/os/basement_prod/619a6f16-ecb0-4fca-9f9a-b06b67f6f02b.json', + ); + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + pitch: 0, + // style: 'dark', + center: [-44.40673828125, -18.375379094031825], + zoom: 13, + }), + }); + this.scene = scene; + const data = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [110.5224609375, 32.731840896865684], + [113.0712890625, 32.731840896865684], + [113.0712890625, 34.56085936708384], + [110.5224609375, 34.56085936708384], + [110.5224609375, 32.731840896865684], + ], + [ + [111.26953125, 33.52307880890422], + [111.26953125, 34.03445260967645], + [112.03857421875, 34.03445260967645], + [112.03857421875, 33.52307880890422], + [111.26953125, 33.52307880890422], + ], + ], + [ + [ + [115.04882812499999, 34.379712580462204], + [114.9609375, 33.46810795527896], + [115.8837890625, 33.50475906922609], + [115.86181640625001, 34.379712580462204], + [115.04882812499999, 34.379712580462204], + ], + ], + ], + }, + }, + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [113.8623046875, 30.031055426540206], + [116.3232421875, 30.031055426540206], + [116.3232421875, 31.090574094954192], + [113.8623046875, 31.090574094954192], + [113.8623046875, 30.031055426540206], + ], + [ + [117.26806640625, 32.13840869677249], + [118.36669921875, 32.13840869677249], + [118.36669921875, 32.47269502206151], + [117.26806640625, 32.47269502206151], + [117.26806640625, 32.13840869677249], + ], + ], + }, + }, + ], + }; + + const layer = new PolygonLayer({ + autoFit: true, + }) + .source(data) + // .shape('fill') + .shape('extrude') + .color('red') + .size(6000000) + .style({ + opacity: 1.0, + }) + .active(true); + scene.addLayer(layer); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/Map/components/amap2demo_text.tsx b/stories/Map/components/amap2demo_text.tsx new file mode 100644 index 0000000000..ea0cafd48b --- /dev/null +++ b/stories/Map/components/amap2demo_text.tsx @@ -0,0 +1,80 @@ +import { vec2, vec3 } from 'gl-matrix'; +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +import { mat4 } from 'gl-matrix'; + +export default class Amap2demo_text extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap2({ + center: [120.19382669582967, 30.258134], + pitch: 0, + style: 'light', + zoom: 3, + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('m', 'text') + .size(12) + .color('w', ['#0e0030', '#0e0030', '#0e0030']) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + // textAllowOverlap: true + }); + + scene.addLayer(pointLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amapdemo_extrude.tsx b/stories/Map/components/amapdemo_extrude.tsx new file mode 100644 index 0000000000..c3e0fe27dc --- /dev/null +++ b/stories/Map/components/amapdemo_extrude.tsx @@ -0,0 +1,84 @@ +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amapdemo_extrude extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [121.107846, 30.267069], + pitch: 35.210526315789465, + style: 'normal', + zoom: 8, + animateEnable: false, + }), + }); + + this.scene = scene; + + scene.on('loaded', () => { + console.log('event test'); + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('cylinder') + .size('t', function(level) { + return [1, 2, level * 2 + 20]; + }) + .active(true) + .color('t', [ + '#094D4A', + '#146968', + '#1D7F7E', + '#289899', + '#34B6B7', + '#4AC5AF', + '#5FD3A6', + '#7BE39E', + '#A1EDB8', + '#CEF8D6', + ]) + .style({ + opacity: 1.0, + }); + scene.addLayer(pointLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/mapCenter.tsx b/stories/Map/components/mapCenter.tsx index 1509dca603..0018b15100 100644 --- a/stories/Map/components/mapCenter.tsx +++ b/stories/Map/components/mapCenter.tsx @@ -18,7 +18,7 @@ export default class GaodeMapComponent extends React.Component { center: [121.107846, 30.267069], pitch: 0, style: 'normal', - zoom: 11, + zoom: 13, animateEnable: false, }), }); @@ -30,6 +30,18 @@ export default class GaodeMapComponent extends React.Component { lng: 121.107846, lat: 30.267069, }, + { + lng: 121.1, + lat: 30.267069, + }, + { + lng: 120.107846, + lat: 30.267069, + }, + { + lng: 38.54, + lat: 77.02, + }, ], { parser: { @@ -40,6 +52,7 @@ export default class GaodeMapComponent extends React.Component { }, ) .shape('circle') + // .shape('normal') .color('blue') .size(10) .style({ @@ -51,27 +64,25 @@ export default class GaodeMapComponent extends React.Component { this.scene = scene; scene.on('loaded', () => { - const padding = { - top: 50, - right: 0, - bottom: 200, - left: 800, - }; + // const padding = { + // top: 50, + // right: 0, + // bottom: 200, + // left: 800, + // }; // const px = scene.lngLatToPixel([center.lng, center.lat]); // const offsetPx = [ // (padding.right - padding.left) / 2, // (padding.bottom - padding.top) / 2, // ]; - scene.setCenter([121.107846, 30.267069], { padding }); + // scene.setCenter([121.107846, 30.267069], { padding }); // const newCenter = scene.pixelToLngLat([ // px.x + offsetPx[0], // px.y + offsetPx[1], // ]); // @ts-ignore // scene.setCenter(); - // get originCenter - // const originCenter = scene.getCenter(); // const originPx = scene.lngLatToPixel([ // originCenter.lng, @@ -85,7 +96,6 @@ export default class GaodeMapComponent extends React.Component { // originPx.x - offsetPx[0], // originPx.y - offsetPx[1], // ]); - // lngLatToContainer // 获取当前地图像素坐标 // console.log(originCenter, center, newCenter2); @@ -106,7 +116,7 @@ export default class GaodeMapComponent extends React.Component { bottom: 0, }} /> -
-
*/} + {/*
+ /> */} ); } diff --git a/stories/Map/map.stories.tsx b/stories/Map/map.stories.tsx index dca527ef51..5428a7850b 100644 --- a/stories/Map/map.stories.tsx +++ b/stories/Map/map.stories.tsx @@ -1,6 +1,24 @@ import { storiesOf } from '@storybook/react'; import * as React from 'react'; import MapCenter from './components/mapCenter'; +import Amap2demo from './components/amap2demo' +import Amap2demo_extrude from './components/amap2demo_extrude' +import Amapdemo_extrude from './components/amapdemo_extrude' +import Amap2demo_text from './components/amap2demo_text' +import Amap2demo_image from './components/amap2demo_image' + +import Amap2demo_polygon from './components/amap2demo_polygon' +import Amap2demo_polygon_extrude from './components/amap2demo_polygon_extrude' +import Amap2demo_arcLine from "./components/amap2demo_arcLine" // @ts-ignore -storiesOf('地图方法', module).add('地图中心点', () => ); +storiesOf('地图方法', module) + .add('高德地图 point/demo', () => ) + .add('高德地图2.0 point/demo', () => ) + .add('高德地图 point/extrude', () => ) + .add('高德地图2.0 point/extrude', () => ) + .add('高德地图2.0 point/text', () => ) + .add('高德地图2.0 point/image', () => ) + .add('高德地图2.0 polygon', () => ) + .add('高德地图2.0 polygon_extrude', () => ) + .add('高德地图2.0 line_arc', () => ) From 6452fd9093ff279bcc949591383c4b6340948b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=8A=E9=92=B1=E8=80=80?= Date: Thu, 22 Apr 2021 15:11:40 +0800 Subject: [PATCH 2/9] feat(text): change text --- packages/layers/src/point/models/text.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/layers/src/point/models/text.ts b/packages/layers/src/point/models/text.ts index 07424931a3..6a876d1040 100644 --- a/packages/layers/src/point/models/text.ts +++ b/packages/layers/src/point/models/text.ts @@ -354,7 +354,10 @@ export default class TextModel extends BaseModel { // // 此时地图不是高德2.0 originCentroid == centroid // feature.originCentroid = feature.centroid; // } - feature.originCentroid = feature.version === 'GAODE2.x'?calculteCentroid(feature.originCoordinates):feature.originCentroid = feature.centroid; + feature.originCentroid = + feature.version === 'GAODE2.x' + ? calculteCentroid(feature.originCoordinates) + : (feature.originCentroid = feature.centroid); this.glyphInfoMap[id as number] = { shaping, @@ -386,7 +389,9 @@ export default class TextModel extends BaseModel { const { shaping, id = 0 } = feature; // const centroid = feature.centroid as [number, number]; // const centroid = feature.originCentroid as [number, number]; - const centroid = (feature.version === 'GAODE2.x'?feature.originCentroid:feature.centroid) as [number, number]; + const centroid = (feature.version === 'GAODE2.x' + ? feature.originCentroid + : feature.centroid) as [number, number]; const size = feature.size as number; const fontScale: number = size / 24; const pixels = this.mapService.lngLatToContainer(centroid); From 48cb8ad8a73b18f3e1204ddedb2638b90e0da5c8 Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Mon, 26 Apr 2021 15:23:42 +0800 Subject: [PATCH 3/9] feat: gaode2.0 not finished --- packages/layers/src/core/triangulation.ts | 4 +- packages/layers/src/heatmap/models/grid.ts | 4 +- packages/layers/src/heatmap/models/grid3d.ts | 4 +- packages/layers/src/heatmap/models/heatmap.ts | 5 +- packages/layers/src/heatmap/models/hexagon.ts | 2 +- .../layers/src/plugins/DataMappingPlugin.ts | 3 +- .../layers/src/plugins/ShaderUniformPlugin.ts | 4 +- packages/layers/src/raster/raster.ts | 2 +- packages/maps/src/amap2/Viewport.ts | 14 ++++- packages/maps/src/amap2/map.ts | 15 +++--- stories/Map/components/amap2demo.tsx | 9 +--- .../Map/components/amap2demo_arcLine3d.tsx | 50 +++++++++-------- .../amap2demo_arcLine_greatCircle.tsx | 54 +++++++++---------- .../Map/components/amap2demo_citybuilding.tsx | 5 +- stories/Map/components/amap2demo_heatmap.tsx | 30 ++++++----- .../Map/components/amap2demo_heatmap3D.tsx | 30 ++++++----- .../Map/components/amap2demo_heatmap_grid.tsx | 34 ++++++------ .../components/amap2demo_heatmap_hexagon.tsx | 34 ++++++------ .../Map/components/amap2demo_imagelayer.tsx | 18 +++---- 19 files changed, 174 insertions(+), 147 deletions(-) diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index a38ce67048..f58e77fea3 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -247,8 +247,8 @@ export function LineArcTriangulation(feature: IEncodeFeature) { /** * 构建热力图密度图的顶点 - * @param feature - * @returns + * @param feature + * @returns */ export function HeatmapTriangulation(feature: IEncodeFeature) { const coordinates = feature.coordinates as number[]; diff --git a/packages/layers/src/heatmap/models/grid.ts b/packages/layers/src/heatmap/models/grid.ts index 5d37cd3788..067b5fe173 100644 --- a/packages/layers/src/heatmap/models/grid.ts +++ b/packages/layers/src/heatmap/models/grid.ts @@ -64,7 +64,9 @@ export default class GridModel extends BaseModel { size: 3, update: (feature: IEncodeFeature, featureIdx: number) => { // const coordinates = feature.coordinates as number[]; - const coordinates = (feature.version==='GAODE2.x'?feature.originCoordinates:feature.coordinates) as number[]; + const coordinates = (feature.version === 'GAODE2.x' + ? feature.originCoordinates + : feature.coordinates) as number[]; return [coordinates[0], coordinates[1], 0]; }, }, diff --git a/packages/layers/src/heatmap/models/grid3d.ts b/packages/layers/src/heatmap/models/grid3d.ts index 27d2303614..ca05e1701f 100644 --- a/packages/layers/src/heatmap/models/grid3d.ts +++ b/packages/layers/src/heatmap/models/grid3d.ts @@ -112,7 +112,9 @@ export default class Grid3DModel extends BaseModel { }, size: 3, update: (feature: IEncodeFeature, featureIdx: number) => { - const coordinates = (feature.version==='GAODE2.x'?feature.originCoordinates:feature.coordinates) as number[]; + const coordinates = (feature.version === 'GAODE2.x' + ? feature.originCoordinates + : feature.coordinates) as number[]; // const coordinates = feature.coordinates as number[]; // const coordinates = feature.originCoordinates as number[]; return [coordinates[0], coordinates[1], 0]; diff --git a/packages/layers/src/heatmap/models/heatmap.ts b/packages/layers/src/heatmap/models/heatmap.ts index 2645061d61..b549954f26 100644 --- a/packages/layers/src/heatmap/models/heatmap.ts +++ b/packages/layers/src/heatmap/models/heatmap.ts @@ -5,10 +5,11 @@ import { IFramebuffer, IModel, IModelUniform, - ITexture2D + ITexture2D, } from '@antv/l7-core'; import { generateColorRamp, IColorRamp } from '@antv/l7-utils'; import { mat4 } from 'gl-matrix'; +import { inject, injectable } from 'inversify'; import BaseModel from '../../core/BaseModel'; import { HeatmapTriangulation } from '../../core/triangulation'; import heatmap3DFrag from '../shaders/heatmap_3d_frag.glsl'; @@ -18,7 +19,6 @@ import heatmapFrag from '../shaders/heatmap_framebuffer_frag.glsl'; import heatmapVert from '../shaders/heatmap_framebuffer_vert.glsl'; import heatmapColorVert from '../shaders/heatmap_vert.glsl'; import { heatMap3DTriangulation } from '../triangulation'; -import { inject, injectable } from 'inversify'; interface IHeatMapLayerStyleOptions { opacity: number; intensity: number; @@ -28,7 +28,6 @@ interface IHeatMapLayerStyleOptions { } @injectable() export default class HeatMapModel extends BaseModel { - protected texture: ITexture2D; protected colorTexture: ITexture2D; protected heatmapFramerBuffer: IFramebuffer; diff --git a/packages/layers/src/heatmap/models/hexagon.ts b/packages/layers/src/heatmap/models/hexagon.ts index 3f14a8479d..5747b65d9d 100644 --- a/packages/layers/src/heatmap/models/hexagon.ts +++ b/packages/layers/src/heatmap/models/hexagon.ts @@ -66,7 +66,7 @@ export default class HexagonModel extends BaseModel { size: 3, update: (feature: IEncodeFeature, featureIdx: number) => { // const coordinates = (feature.verison==='GAODE2.x'?feature.originoordinates:feature.coordinates) as number[]; - + const coordinates = feature.coordinates as number[]; // const coordinates = feature.originCoordinates as number[]; return [coordinates[0], coordinates[1], 0]; diff --git a/packages/layers/src/plugins/DataMappingPlugin.ts b/packages/layers/src/plugins/DataMappingPlugin.ts index d583946915..c4adb9b0c9 100644 --- a/packages/layers/src/plugins/DataMappingPlugin.ts +++ b/packages/layers/src/plugins/DataMappingPlugin.ts @@ -137,9 +137,8 @@ export default class DataMappingPlugin implements ILayerPlugin { // 根据地图的类型判断是否需要对点位数据进行处理 if (this.mapService.version === 'GAODE2.x') { // 若是高德2.0则需要对坐标进行相对偏移 - + if (typeof mappedData[0].coordinates[0] === 'number') { - // console.log('111', mappedData) // 单个的点数据 // @ts-ignore diff --git a/packages/layers/src/plugins/ShaderUniformPlugin.ts b/packages/layers/src/plugins/ShaderUniformPlugin.ts index c507bb5d36..e7f4e48685 100644 --- a/packages/layers/src/plugins/ShaderUniformPlugin.ts +++ b/packages/layers/src/plugins/ShaderUniformPlugin.ts @@ -37,7 +37,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin { const version = this.mapService.version; let mvp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; // default matrix (for gaode2.x) - let sceneCenterMKT = [0, 0] + let sceneCenterMKT = [0, 0]; layer.hooks.beforeRender.tap('ShaderUniformPlugin', () => { // 重新计算坐标系参数 this.coordinateSystemService.refresh(); @@ -47,7 +47,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin { mvp = this.mapService.map.customCoords.getMVPMatrix(); // mvp = amapCustomCoords.getMVPMatrix() // @ts-ignore - sceneCenterMKT = this.mapService.getCustomCoordCenter() + sceneCenterMKT = this.mapService.getCustomCoordCenter(); } const { width, height } = this.rendererService.getViewportSize(); diff --git a/packages/layers/src/raster/raster.ts b/packages/layers/src/raster/raster.ts index 33ee0ba48f..05216ba8c4 100644 --- a/packages/layers/src/raster/raster.ts +++ b/packages/layers/src/raster/raster.ts @@ -18,7 +18,7 @@ import BaseLayer from '../core/BaseLayer'; import { RasterTriangulation } from './buffers/triangulation'; import rasterFrag from './shaders/raster_frag.glsl'; import rasterVert from './shaders/raster_vert.glsl'; -interface IRasterLayerStyleOptions { +interface IRasterLayerStyleOptions { opacity: number; min: number; max: number; diff --git a/packages/maps/src/amap2/Viewport.ts b/packages/maps/src/amap2/Viewport.ts index 22b8e0ba34..985df243f6 100644 --- a/packages/maps/src/amap2/Viewport.ts +++ b/packages/maps/src/amap2/Viewport.ts @@ -32,14 +32,24 @@ export default class Viewport implements IViewport { this.center = center; // 计算透视投影矩阵 projectionMatrix - mat4.perspective(this.projectionMatrix, fov/180*Math.PI, aspect, near, far); + mat4.perspective( + this.projectionMatrix, + (fov / 180) * Math.PI, + aspect, + near, + far, + ); // mat4.perspective(this.projectionMatrix, 0.91, aspect, near, far); // const pitchInRadians = pitch * DEGREES_TO_RADIANS; // const rotationInRadians = (360 - bearing) * DEGREES_TO_RADIANS; // 计算相机矩阵 viewMatrix // const eyePoint = vec3.fromValues(...cameraPosition); - const eyePoint = vec3.fromValues(cameraPosition[0], cameraPosition[1], cameraPosition[2]); + const eyePoint = vec3.fromValues( + cameraPosition[0], + cameraPosition[1], + cameraPosition[2], + ); // 计算相机矩阵 viewMatrix // const eyePoint = vec3.fromValues( // (cameraPosition[2]) * Math.sin(pitchInRadians) * Math.sin(rotationInRadians), diff --git a/packages/maps/src/amap2/map.ts b/packages/maps/src/amap2/map.ts index 56152c317f..8d178134ff 100644 --- a/packages/maps/src/amap2/map.ts +++ b/packages/maps/src/amap2/map.ts @@ -524,10 +524,10 @@ export default class AMapService } = this.map.customCoords.getCameraParams(); // @ts-ignore - const center = this.map.customCoords.getCenter() as [number, number] + const center = this.map.customCoords.getCenter() as [number, number]; const zoom = this.map.getZoom(); - const pitch = this.map.getPitch() - const rotation = this.map.getRotation() + const pitch = this.map.getPitch(); + const rotation = this.map.getRotation(); // @ts-ignore if (this.cameraChangedCallback) { this.viewport.syncWithMapCamera({ @@ -541,7 +541,7 @@ export default class AMapService // AMap 定义的缩放等级 与 Mapbox 相差 1 zoom: zoom - 1, // 与amap1.x对比相差一个级别 // center: [center.getLng(), center.getLat()], - center: center, + center, offsetOrigin: [position[0], position[1]], pitch, @@ -568,7 +568,6 @@ export default class AMapService * @param e */ private handleViewChanged = (e: any): void => { - // @ts-ignore const { // @ts-ignore @@ -591,8 +590,8 @@ export default class AMapService // console.log(this.viewport) // console.log('zoom', zoom, this.map.getZoom()) // const center = this.map.getCenter(); - // @ts-ignore - const center = this.map.customCoords.getCenter() as [number, number] + // @ts-ignore + const center = this.map.customCoords.getCenter() as [number, number]; if (this.cameraChangedCallback) { // resync viewport this.viewport.syncWithMapCamera({ @@ -606,7 +605,7 @@ export default class AMapService // AMap 定义的缩放等级 与 Mapbox 相差 1 zoom: zoom - 1, // 与amap1.x对比相差一个级别 // center: [center.getLng(), center.getLat()], - center: center, + center, offsetOrigin: [position[0], position[1]], pitch, diff --git a/stories/Map/components/amap2demo.tsx b/stories/Map/components/amap2demo.tsx index a53dd933b1..956f40d5d1 100644 --- a/stories/Map/components/amap2demo.tsx +++ b/stories/Map/components/amap2demo.tsx @@ -1,11 +1,6 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; - -import { mat4 } from 'gl-matrix'; - export default class Amap2demo extends React.Component { // @ts-ignore private scene: Scene; @@ -48,9 +43,9 @@ export default class Amap2demo extends React.Component { scene.on('loaded', () => { console.log('event test'); // @ts-ignore - console.log(scene.map.getProjection().project) + console.log(scene.map.getProjection().project); // @ts-ignore - console.log(scene.map.customCoords.lngLatToCoord) + console.log(scene.map.customCoords.lngLatToCoord); const layer = new PointLayer() .source(originData, { parser: { diff --git a/stories/Map/components/amap2demo_arcLine3d.tsx b/stories/Map/components/amap2demo_arcLine3d.tsx index f8121d3b62..4f15acda75 100644 --- a/stories/Map/components/amap2demo_arcLine3d.tsx +++ b/stories/Map/components/amap2demo_arcLine3d.tsx @@ -1,5 +1,3 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -17,26 +15,36 @@ export default class Amap2demo_arcLine3d extends React.Component { id: 'map', map: new GaodeMap2({ pitch: 40, - center: [ 3.438, 40.16797 ], - zoom: 0 + center: [3.438, 40.16797], + zoom: 0, }), }); this.scene = scene; scene.on('loaded', () => { Promise.all([ - fetch('https://gw.alipayobjects.com/os/basement_prod/dbd008f1-9189-461c-88aa-569357ffc07d.json').then(d => d.json()), - fetch('https://gw.alipayobjects.com/os/basement_prod/4472780b-fea1-4fc2-9e4b-3ca716933dc7.json').then(d => d.text()), - fetch('https://gw.alipayobjects.com/os/basement_prod/a5ac7bce-181b-40d1-8a16-271356264ad8.json').then(d => d.text()) - ]).then(function onLoad([ world, dot, flyline ]) { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/dbd008f1-9189-461c-88aa-569357ffc07d.json', + ).then((d) => d.json()), + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/4472780b-fea1-4fc2-9e4b-3ca716933dc7.json', + ).then((d) => d.text()), + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/a5ac7bce-181b-40d1-8a16-271356264ad8.json', + ).then((d) => d.text()), + ]).then(function onLoad([world, dot, flyline]) { const dotData = eval(dot); // @ts-ignore - const flydata = eval(flyline).map(item => { + const flydata = eval(flyline).map((item) => { // @ts-ignore - const latlng1 = item.from.split(',').map(e => { return e * 1; }); + const latlng1 = item.from.split(',').map((e) => { + return e * 1; + }); // @ts-ignore - const latlng2 = item.to.split(',').map(e => { return e * 1; }); - return { coord: [ latlng1, latlng2 ] }; + const latlng2 = item.to.split(',').map((e) => { + return e * 1; + }); + return { coord: [latlng1, latlng2] }; }); // const worldFill = new PolygonLayer() // .source(world) @@ -45,35 +53,35 @@ export default class Amap2demo_arcLine3d extends React.Component { // .style({ // opacity: 1 // }); - + const worldLine = new LineLayer() .source(world) .color('#41fc9d') .size(0.5) .style({ - opacity: 0.4 + opacity: 0.4, }); const dotPoint = new PointLayer() .source(dotData, { parser: { type: 'json', x: 'lng', - y: 'lat' - } + y: 'lat', + }, }) .shape('circle') .color('#ffed11') .animate(true) .size(40) .style({ - opacity: 1.0 + opacity: 1.0, }); const flyLine = new LineLayer() .source(flydata, { parser: { type: 'json', - coordinates: 'coord' - } + coordinates: 'coord', + }, }) .color('#ff6b34') .shape('arc3d') @@ -82,10 +90,10 @@ export default class Amap2demo_arcLine3d extends React.Component { .animate({ interval: 2, trailLength: 2, - duration: 1 + duration: 1, }) .style({ - opacity: 1 + opacity: 1, }); // scene.addLayer(worldFill); scene.addLayer(worldLine); diff --git a/stories/Map/components/amap2demo_arcLine_greatCircle.tsx b/stories/Map/components/amap2demo_arcLine_greatCircle.tsx index 3d7c8738b0..5a3fdb0eff 100644 --- a/stories/Map/components/amap2demo_arcLine_greatCircle.tsx +++ b/stories/Map/components/amap2demo_arcLine_greatCircle.tsx @@ -1,5 +1,3 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -25,31 +23,33 @@ export default class Amap2demo_arcLine_greatCircle extends React.Component { scene.on('loaded', () => { const layer = new LineLayer({}) - .source([ - { - lng1: 75.9375, - lat1: 37.71859032558816, - lng2: 123.3984375, - lat2: 39.639537564366684 - } - ], { - parser: { - type: 'json', - x: 'lng1', - y: 'lat1', - x1: 'lng2', - y1: 'lat2', - }, - }) - .size(1) - .shape('greatcircle') - .color('#ff0000') - .style({ - opacity: 0.8, - blur: 0.99, - }); - scene.addLayer(layer); - + .source( + [ + { + lng1: 75.9375, + lat1: 37.71859032558816, + lng2: 123.3984375, + lat2: 39.639537564366684, + }, + ], + { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }, + ) + .size(1) + .shape('greatcircle') + .color('#ff0000') + .style({ + opacity: 0.8, + blur: 0.99, + }); + scene.addLayer(layer); }); } diff --git a/stories/Map/components/amap2demo_citybuilding.tsx b/stories/Map/components/amap2demo_citybuilding.tsx index befa2db63d..6ee3c91329 100644 --- a/stories/Map/components/amap2demo_citybuilding.tsx +++ b/stories/Map/components/amap2demo_citybuilding.tsx @@ -1,8 +1,6 @@ import { PointLayer, CityBuildingLayer, Scene } from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; -import * as dat from 'dat.gui'; - export default class Amap2demo_citybuilding extends React.Component { // @ts-ignore @@ -22,7 +20,7 @@ export default class Amap2demo_citybuilding extends React.Component { style: 'dark', center: [121.507674, 31.223043], pitch: 65.59312320916906, - zoom: 15.4 + zoom: 15.4, }), }); const pointLayer = new CityBuildingLayer(); @@ -42,7 +40,6 @@ export default class Amap2demo_citybuilding extends React.Component { scene.addLayer(pointLayer); this.scene = scene; - } public render() { diff --git a/stories/Map/components/amap2demo_heatmap.tsx b/stories/Map/components/amap2demo_heatmap.tsx index a985a1751a..68c88ae3ba 100644 --- a/stories/Map/components/amap2demo_heatmap.tsx +++ b/stories/Map/components/amap2demo_heatmap.tsx @@ -1,6 +1,10 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore -import { ILngLat, PointLayer, PolygonLayer, Scene, HeatmapLayer } from '@antv/l7'; +import { + ILngLat, + PointLayer, + PolygonLayer, + Scene, + HeatmapLayer, +} from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -17,22 +21,22 @@ export default class Amap2demo_heatmap extends React.Component { id: 'map', map: new GaodeMap2({ pitch: 0, - center: [ 127.5671666579043, 7.445038892195569 ], - zoom: 2.632456779444394 + center: [127.5671666579043, 7.445038892195569], + zoom: 2.632456779444394, }), }); this.scene = scene; scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json' + 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', ) - .then(res => res.json()) - .then(data => { + .then((res) => res.json()) + .then((data) => { const layer = new HeatmapLayer({}) .source(data) .shape('heatmap') - .size('mag', [ 0, 1.0 ]) // weight映射通道 + .size('mag', [0, 1.0]) // weight映射通道 .style({ intensity: 2, radius: 20, @@ -44,13 +48,13 @@ export default class Amap2demo_heatmap extends React.Component { '#FFF598', '#91EABC', '#2EA9A1', - '#206C7C' + '#206C7C', ].reverse(), - positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ] - } + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, }); scene.addLayer(layer); - }) + }); }); } diff --git a/stories/Map/components/amap2demo_heatmap3D.tsx b/stories/Map/components/amap2demo_heatmap3D.tsx index c20b994bbe..17c38018f7 100644 --- a/stories/Map/components/amap2demo_heatmap3D.tsx +++ b/stories/Map/components/amap2demo_heatmap3D.tsx @@ -1,6 +1,10 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore -import { ILngLat, PointLayer, PolygonLayer, Scene, HeatmapLayer } from '@antv/l7'; +import { + ILngLat, + PointLayer, + PolygonLayer, + Scene, + HeatmapLayer, +} from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -18,24 +22,24 @@ export default class Amap2demo_heatmap extends React.Component { map: new GaodeMap2({ // pitch: 58.5, pitch: 0, - center: [ 111.8759, 30.6942 ], + center: [111.8759, 30.6942], rotation: 0.519, - zoom: 3.6116 + zoom: 3.6116, }), }); this.scene = scene; scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64359241955.json' + 'https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64359241955.json', ) - .then(res => res.json()) - .then(data => { + .then((res) => res.json()) + .then((data) => { const layer = new HeatmapLayer({}) .source(data) - .size('capacity', [ 0, 1 ]) + .size('capacity', [0, 1]) .shape('heatmap3D') - // weight映射通道 + // weight映射通道 .style({ intensity: 10, radius: 5, @@ -47,10 +51,10 @@ export default class Amap2demo_heatmap extends React.Component { '#DAF291', '#FFD591', '#FF7A45', - '#CF1D49' + '#CF1D49', ], - positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ] - } + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, }); scene.addLayer(layer); }); diff --git a/stories/Map/components/amap2demo_heatmap_grid.tsx b/stories/Map/components/amap2demo_heatmap_grid.tsx index 1ba8aef4b4..637e2f8474 100644 --- a/stories/Map/components/amap2demo_heatmap_grid.tsx +++ b/stories/Map/components/amap2demo_heatmap_grid.tsx @@ -1,6 +1,10 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore -import { ILngLat, PointLayer, PolygonLayer, Scene, HeatmapLayer } from '@antv/l7'; +import { + ILngLat, + PointLayer, + PolygonLayer, + Scene, + HeatmapLayer, +} from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -17,38 +21,38 @@ export default class Amap2demo_heatmap_grid extends React.Component { id: 'map', map: new GaodeMap2({ pitch: 0, - center: [ 110.097892, 33.853662 ], - zoom: 4.056 + center: [110.097892, 33.853662], + zoom: 4.056, }), }); this.scene = scene; scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv' + 'https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv', ) - .then(res => res.text()) - .then(data => { + .then((res) => res.text()) + .then((data) => { const layer = new HeatmapLayer({}) .source(data, { parser: { type: 'csv', x: 'lng', - y: 'lat' + y: 'lat', }, transforms: [ { type: 'grid', size: 20000, field: 'v', - method: 'sum' - } - ] + method: 'sum', + }, + ], }) .shape('circle') .style({ coverage: 0.9, - angle: 0 + angle: 0, }) .color( 'count', @@ -64,8 +68,8 @@ export default class Amap2demo_heatmap_grid extends React.Component { '#F77B00', '#ED9909', '#ECC357', - '#EDE59C' - ].reverse() + '#EDE59C', + ].reverse(), ); scene.addLayer(layer); }); diff --git a/stories/Map/components/amap2demo_heatmap_hexagon.tsx b/stories/Map/components/amap2demo_heatmap_hexagon.tsx index eaa1d99d4e..8aeddbfca7 100644 --- a/stories/Map/components/amap2demo_heatmap_hexagon.tsx +++ b/stories/Map/components/amap2demo_heatmap_hexagon.tsx @@ -1,6 +1,10 @@ -import { vec2, vec3 } from 'gl-matrix'; -// @ts-ignore -import { ILngLat, PointLayer, PolygonLayer, Scene, HeatmapLayer } from '@antv/l7'; +import { + ILngLat, + PointLayer, + PolygonLayer, + Scene, + HeatmapLayer, +} from '@antv/l7'; import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; import * as React from 'react'; @@ -18,42 +22,42 @@ export default class Amap2demo_heatmap_hexagon extends React.Component { map: new GaodeMap2({ // pitch: 58.5, pitch: 43, - center: [ 120.13383079335335, 29.651873105004427 ], - zoom: 7.068989519212174 + center: [120.13383079335335, 29.651873105004427], + zoom: 7.068989519212174, }), }); this.scene = scene; scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/basement_prod/a1a8158d-6fe3-424b-8e50-694ccf61c4d7.csv' + 'https://gw.alipayobjects.com/os/basement_prod/a1a8158d-6fe3-424b-8e50-694ccf61c4d7.csv', ) - .then(res => res.text()) - .then(data => { + .then((res) => res.text()) + .then((data) => { const layer = new HeatmapLayer({}) .source(data, { parser: { type: 'csv', x: 'lng', - y: 'lat' + y: 'lat', }, transforms: [ { type: 'hexagon', size: 2500, field: 'v', - method: 'sum' - } - ] + method: 'sum', + }, + ], }) - .size('sum', sum => { + .size('sum', (sum) => { return sum * 200; }) .shape('hexagonColumn') .style({ coverage: 0.8, angle: 0, - opacity: 1.0 + opacity: 1.0, }) .color('sum', [ '#094D4A', @@ -67,7 +71,7 @@ export default class Amap2demo_heatmap_hexagon extends React.Component { '#A1EDB8', '#C3F9CC', '#DEFAC0', - '#ECFFB1' + '#ECFFB1', ]); scene.addLayer(layer); }); diff --git a/stories/Map/components/amap2demo_imagelayer.tsx b/stories/Map/components/amap2demo_imagelayer.tsx index 442152033c..a608db490c 100644 --- a/stories/Map/components/amap2demo_imagelayer.tsx +++ b/stories/Map/components/amap2demo_imagelayer.tsx @@ -24,16 +24,16 @@ export default class Amap2demo_imageLayer extends React.Component { scene.on('loaded', () => { const layer = new ImageLayer({}); - layer.source( - 'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', - { - parser: { - type: 'image', - extent: [121.168, 30.2828, 121.384, 30.4219], + layer.source( + 'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', + { + parser: { + type: 'image', + extent: [121.168, 30.2828, 121.384, 30.4219], + }, }, - }, - ); - scene.addLayer(layer); + ); + scene.addLayer(layer); }); } From b7d2b5b1537fdae5283c015fa8443897357bfd90 Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Thu, 27 May 2021 19:53:22 +0800 Subject: [PATCH 4/9] feat: 2.4 beta --- docs/api/layer/layer.zh.md | 4 +- docs/api/layer/line_layer/arc.zh.md | 2 +- docs/api/layer/line_layer/linelayer.en.md | 70 +- docs/api/layer/line_layer/linelayer.zh.md | 70 +- docs/api/layer/point_layer/pointlayer.zh.md | 2 +- docs/api/map.zh.md | 23 +- docs/api/scene.zh.md | 304 +++++++-- docs/api/source/source.zh.md | 4 +- docs/common/layer/options.md | 4 +- .../district/drill/demo/drill_down_view.js | 4 +- examples/district/drill/demo/meta.json | 10 + examples/district/react/demo/province.tsx | 2 +- .../animate/demo/animate_path_texture.js | 40 ++ examples/gallery/animate/demo/build.js | 2 +- examples/gallery/animate/demo/meta.json | 5 + examples/line/animate/demo/meta.json | 5 + examples/line/animate/demo/wind.js | 41 ++ examples/line/path/demo/meta.json | 9 +- examples/line/path/demo/road_red.js | 33 + examples/point/image/demo/meta.json | 5 + examples/point/image/demo/road.js | 106 ++++ examples/point/scatter/demo/animatePoint.js | 54 ++ examples/point/scatter/demo/dynamicScatter.js | 52 ++ examples/point/scatter/demo/meta.json | 12 +- examples/point/text/demo/iconfont.js | 77 +++ examples/point/text/demo/iconfonts.js | 225 +++++++ examples/point/text/demo/meta.json | 16 +- examples/point/text/demo/point_text.js | 3 +- examples/point/text/demo/temperture.js | 103 +++ examples/react/covid/index.zh.md | 2 +- examples/react/layer/demo/Point_image.tsx | 4 +- examples/react/layer/demo/meta.json | 6 +- examples/react/layer/demo/popup.tsx | 1 + examples/tutorial/layer/demo/mapbox.js | 17 - examples/tutorial/layer/demo/meta.json | 11 +- examples/tutorial/map/demo/amapInstance.js | 3 +- examples/tutorial/map/demo/amapInstance2d.js | 58 ++ examples/tutorial/map/demo/meta.json | 7 +- gatsby-config.js | 2 +- packages/component/src/control/BaseControl.ts | 2 +- packages/component/src/css/l7.css | 2 - packages/component/src/marker.ts | 3 +- .../core/src/services/asset/FontService.ts | 83 ++- .../core/src/services/asset/IFontService.ts | 8 + .../core/src/services/asset/IconService.ts | 8 + .../core/src/services/camera/CameraService.ts | 13 +- .../core/src/services/config/ConfigService.ts | 1 + .../core/src/services/layer/ILayerService.ts | 7 + .../core/src/services/scene/ISceneService.ts | 3 + .../core/src/services/scene/SceneService.ts | 29 + packages/core/src/shaders/project.glsl | 18 +- packages/core/src/shaders/projection.glsl | 2 +- packages/core/src/utils/font_util.ts | 1 - packages/layers/src/core/BaseLayer.ts | 12 +- packages/layers/src/core/interface.ts | 3 + packages/layers/src/core/triangulation.ts | 21 +- packages/layers/src/heatmap/models/heatmap.ts | 21 +- packages/layers/src/heatmap/models/hexagon.ts | 6 +- .../src/heatmap/shaders/hexagon_vert.glsl | 14 +- packages/layers/src/line/models/arc.ts | 2 + packages/layers/src/line/models/line.ts | 102 +++ .../src/line/shaders/line_arc_vert.glsl | 13 +- .../layers/src/line/shaders/line_frag.glsl | 44 +- .../layers/src/line/shaders/line_vert.glsl | 28 +- .../layers/src/plugins/DataMappingPlugin.ts | 25 +- packages/layers/src/point/models/image.ts | 1 - packages/layers/src/point/models/text.ts | 53 +- .../layers/src/point/shaders/image_frag.glsl | 18 +- packages/layers/src/raster/raster.ts | 6 +- packages/layers/src/raster/raster2d.ts | 8 +- packages/layers/src/utils/extrude_polyline.ts | 599 ++++++++---------- packages/layers/src/utils/symbol-layout.ts | 106 +++- packages/maps/src/amap2/Viewport.ts | 47 +- packages/maps/src/amap2/map.ts | 81 +-- packages/maps/src/amap2/theme.ts | 9 +- packages/maps/src/index.ts | 7 +- packages/maps/src/mapbox/map.ts | 2 +- packages/maps/typings/index.d.ts | 1 + packages/scene/src/index.ts | 23 + stories/Components/components/Popup.tsx | 4 +- stories/Layers/components/RasterLayer.tsx | 1 + stories/Map/components/amap2demo.tsx | 7 +- stories/Map/components/amap2demo_arcLine.tsx | 15 +- .../Map/components/amap2demo_arcLine3d.tsx | 8 +- .../Map/components/amap2demo_arcLineDir.tsx | 174 +++++ .../amap2demo_arcLine_greatCircle.tsx | 8 +- .../Map/components/amap2demo_citybuilding.tsx | 8 +- .../Map/components/amap2demo_drawControl.tsx | 63 ++ .../Map/components/amap2demo_drilldown.tsx | 69 ++ stories/Map/components/amap2demo_extrude.tsx | 5 +- stories/Map/components/amap2demo_heatmap.tsx | 13 +- .../Map/components/amap2demo_heatmap3D.tsx | 14 +- .../Map/components/amap2demo_heatmap_grid.tsx | 13 +- .../components/amap2demo_heatmap_hexagon.tsx | 14 +- .../amap2demo_heatmap_hexagon_world.tsx | 74 +++ stories/Map/components/amap2demo_iconfont.tsx | 259 ++++++++ stories/Map/components/amap2demo_image.tsx | 13 +- .../Map/components/amap2demo_imagelayer.tsx | 6 +- stories/Map/components/amap2demo_instance.tsx | 102 +++ stories/Map/components/amap2demo_lineDash.tsx | 64 ++ .../Map/components/amap2demo_lineHeight.tsx | 78 +++ .../Map/components/amap2demo_lineStreet.tsx | 82 +++ .../Map/components/amap2demo_markerlayer.tsx | 81 +++ stories/Map/components/amap2demo_mesh.tsx | 165 +++++ stories/Map/components/amap2demo_polygon.tsx | 18 +- .../components/amap2demo_polygon_extrude.tsx | 4 +- .../Map/components/amap2demo_rasterlayer.tsx | 7 +- stories/Map/components/amap2demo_road.tsx | 138 ++++ stories/Map/components/amap2demo_text.tsx | 128 +++- stories/Map/components/amap2demo_winds.tsx | 73 +++ stories/Map/components/amapdemo_extrude.tsx | 2 +- stories/Map/map.stories.tsx | 41 ++ 112 files changed, 3785 insertions(+), 796 deletions(-) create mode 100644 examples/gallery/animate/demo/animate_path_texture.js create mode 100644 examples/line/animate/demo/wind.js create mode 100644 examples/line/path/demo/road_red.js create mode 100644 examples/point/image/demo/road.js create mode 100644 examples/point/scatter/demo/animatePoint.js create mode 100644 examples/point/scatter/demo/dynamicScatter.js create mode 100644 examples/point/text/demo/iconfont.js create mode 100644 examples/point/text/demo/iconfonts.js create mode 100644 examples/point/text/demo/temperture.js delete mode 100644 examples/tutorial/layer/demo/mapbox.js create mode 100644 examples/tutorial/map/demo/amapInstance2d.js create mode 100644 stories/Map/components/amap2demo_arcLineDir.tsx create mode 100644 stories/Map/components/amap2demo_drawControl.tsx create mode 100644 stories/Map/components/amap2demo_drilldown.tsx create mode 100644 stories/Map/components/amap2demo_heatmap_hexagon_world.tsx create mode 100644 stories/Map/components/amap2demo_iconfont.tsx create mode 100644 stories/Map/components/amap2demo_instance.tsx create mode 100644 stories/Map/components/amap2demo_lineDash.tsx create mode 100644 stories/Map/components/amap2demo_lineHeight.tsx create mode 100644 stories/Map/components/amap2demo_lineStreet.tsx create mode 100644 stories/Map/components/amap2demo_markerlayer.tsx create mode 100644 stories/Map/components/amap2demo_mesh.tsx create mode 100644 stories/Map/components/amap2demo_road.tsx create mode 100644 stories/Map/components/amap2demo_winds.tsx diff --git a/docs/api/layer/layer.zh.md b/docs/api/layer/layer.zh.md index 526f53f325..aaae44fbe8 100644 --- a/docs/api/layer/layer.zh.md +++ b/docs/api/layer/layer.zh.md @@ -42,11 +42,11 @@ scene.addLayer(layer); ### minZoom -图层显示最小缩放等级,(0-18)   {number}  Mapbox (0-24) 高德 (3-18) +图层显示最小缩放等级,(0-18)   {number}  Mapbox (0-24) 高德 (2-19) ### maxZoom -图层显示最大缩放等级 (0-18)   {number}  Mapbox (0-24) 高德 (3-18) +图层显示最大缩放等级 (0-18)   {number}  Mapbox (0-24) 高德 (2-19) ### autoFit diff --git a/docs/api/layer/line_layer/arc.zh.md b/docs/api/layer/line_layer/arc.zh.md index 182b2dac6b..fccf55343d 100644 --- a/docs/api/layer/line_layer/arc.zh.md +++ b/docs/api/layer/line_layer/arc.zh.md @@ -9,7 +9,7 @@ order: 1 ### 数据 -绘制弧线只需提供起止点坐标即可 +绘制弧线只需提供起止点坐标即可(起止点调换位置,弧线的形状会对称相反,飞线动画的方向也会相反) ```javascript source(data, { diff --git a/docs/api/layer/line_layer/linelayer.en.md b/docs/api/layer/line_layer/linelayer.en.md index cc2a1241a7..29a58ccfda 100644 --- a/docs/api/layer/line_layer/linelayer.en.md +++ b/docs/api/layer/line_layer/linelayer.en.md @@ -1,71 +1,5 @@ --- title: LineLayer -order: 2 +order: 0 --- -`markdown:docs/common/style.md` -## 线图层 - -### shape - -线图层支持 4 种 shape - -- line 绘制路径图, -- arc 绘制弧线 通过贝塞尔曲线算法技术弧线 -- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线 -- arc3d 3d 弧线地图 3D 视角 - -⚠️ 弧线只需要设置起止点坐标即可 - -``` - new LineLayer() - .source(data, { - parser: { - type: 'csv', - x: 'lng1', - y: 'lat1', - x1: 'lng2', - y1: 'lat2', - }, - }) -``` - -如果 geojson 数据绘制弧线图 coordinates 第一对坐标为起点,第二对为终点 - -``` -{ - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - 106.5234375, - 57.51582286553883 - ], - [ - 136.40625, - 61.77312286453146 - ] - ] - } - } - ] -} - -``` - -### size - -线图层 可以设置高度 - -- size 类型为 number 则表示 line 的宽度 -- size 类型为 [number , number] 分别表示宽度和高度 - -```javascript -lineLayer.size(1); // 线的宽度为 1 -lineLayer.size([1, 2]); // 宽度为1,高度2 -``` -`markdown:docs/common/layer/base.md` +`markdown:docs/api/layer/line_layer/linelayer.zh.md` diff --git a/docs/api/layer/line_layer/linelayer.zh.md b/docs/api/layer/line_layer/linelayer.zh.md index ee564bb1dc..cc2a1241a7 100644 --- a/docs/api/layer/line_layer/linelayer.zh.md +++ b/docs/api/layer/line_layer/linelayer.zh.md @@ -1,5 +1,71 @@ --- title: LineLayer -order: 0 +order: 2 --- -`markdown:docs/api/layer/line_layer/linelayer.en.md` +`markdown:docs/common/style.md` +## 线图层 + +### shape + +线图层支持 4 种 shape + +- line 绘制路径图, +- arc 绘制弧线 通过贝塞尔曲线算法技术弧线 +- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线 +- arc3d 3d 弧线地图 3D 视角 + +⚠️ 弧线只需要设置起止点坐标即可 + +``` + new LineLayer() + .source(data, { + parser: { + type: 'csv', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) +``` + +如果 geojson 数据绘制弧线图 coordinates 第一对坐标为起点,第二对为终点 + +``` +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 106.5234375, + 57.51582286553883 + ], + [ + 136.40625, + 61.77312286453146 + ] + ] + } + } + ] +} + +``` + +### size + +线图层 可以设置高度 + +- size 类型为 number 则表示 line 的宽度 +- size 类型为 [number , number] 分别表示宽度和高度 + +```javascript +lineLayer.size(1); // 线的宽度为 1 +lineLayer.size([1, 2]); // 宽度为1,高度2 +``` +`markdown:docs/common/layer/base.md` diff --git a/docs/api/layer/point_layer/pointlayer.zh.md b/docs/api/layer/point_layer/pointlayer.zh.md index d26da1226e..1ffc49c73a 100644 --- a/docs/api/layer/point_layer/pointlayer.zh.md +++ b/docs/api/layer/point_layer/pointlayer.zh.md @@ -34,7 +34,7 @@ shape 支持 **图片标注** -通过 `Scene.addImage()` 可以添加图片资源, +通过 `Scene.addImage()` 可以添加图片资源 ### 代码示例 diff --git a/docs/api/map.zh.md b/docs/api/map.zh.md index 3039eb9839..c2685e7b17 100644 --- a/docs/api/map.zh.md +++ b/docs/api/map.zh.md @@ -15,7 +15,8 @@ L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管 ### 引入 Map ```javascript -import { GaodeMap } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; // 默认引入高德2.0 +import { GaodeMapV1 } from '@antv/l7-maps'; // 默认引入高德1.x 版本 import { Mapbox } from '@antv/l7-maps'; ``` @@ -70,15 +71,15 @@ const scene = new Scene({ ⚠️ 传入地图实例需要自行引入相关地图的 API -⚠️ viewMode 设置为 3D 模式 +⚠️ viewMode 设置为 3D 模式(GaodeMap2.0 支持 2D 模式,可以不设置) #### 传入高德地图实例 ```javascript const map = new AMap.Map('map', { viewMode: '3D', - resizeEnable: true, // 是否监控地图容器尺寸变化 - zoom: 11, // 初始化地图层级 + resizeEnable: true, // 是否监控地图容器尺寸变化 + zoom: 11, // 初始化地图层级 center: [116.397428, 39.90923], // 初始化地图中心点 }); const scene = new Scene({ @@ -92,16 +93,18 @@ const scene = new Scene({ [示例地址](/zh/examples/tutorial/map#amapInstance) [代码地址](https://github.com/antvis/L7/blob/master/examples/tutorial/map/demo/amapInstance.js) +[示例地址( 2D )](/zh/examples/tutorial/map#amapInstance2d) +[代码地址](https://github.com/antvis/L7/blob/master/examples/tutorial/map/demo/amapInstance.js) + #### 传入 Mapbox 地图实例 ```javascript -mapboxgl.accessToken = - 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ'; +mapboxgl.accessToken = 'xxxx - token'; const map = new mapboxgl.Map({ - container: 'map', // container id - style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location - center: [-74.5, 40], // starting position [lng, lat] - zoom: 9, // starting zoom + container: 'map', // container id + style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location + center: [-74.5, 40], // starting position [lng, lat] + zoom: 9, // starting zoom }); const scene = new Scene({ diff --git a/docs/api/scene.zh.md b/docs/api/scene.zh.md index 19ece062df..5a7f4a3215 100644 --- a/docs/api/scene.zh.md +++ b/docs/api/scene.zh.md @@ -113,7 +113,7 @@ L7 Logo 的显示位置 默认左下角 _number_ -地图初始显示级别 {number} Mapbox (0-24) 高德 (3-18) +地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 @@ -146,11 +146,11 @@ L7 Logo 的显示位置 默认左下角 ### minZoom 最小缩放等级 -地图最小缩放等级 {number}  default 0 Mapbox 0-24) 高德 (3-18) +地图最小缩放等级 {number}  default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 -地图最大缩放等级 {number}  default 22 Mapbox(0-24) 高德 (3-18) +地图最大缩放等级 {number}  default 22 Mapbox(0-24) 高德 (2-19) ### rotateEnable 是否允许旋转 @@ -166,7 +166,163 @@ L7 Logo 的显示位置 默认左下角 高德地图适用,是否关闭偏移坐标系 -## 方法 +## Layer 方法 + +### addLayer(layer) 增加图层对象 + +增加图层对象 + +参数 : +- `layer` {ILayer} 图层对象 + +```javascript +scene.addLayer(layer); +``` + +### getLayer(id) 获取对应的图层对象 + +获取对应的图层对象 + +参数 : +- `id` {string} +```javascript +scene.getLayer('layerID'); +``` +### getLayers() 获取所有的地图图层 + +获取所有的地图图层 + +```javascript +scene.getLayers(); +``` + +### getLayerByName(name) 根据图层名称获取图层 + +根据图层名称获取图层 + +参数 + +- `name` {string} layer 初始化可配置图层 name + +```javascript +scene.getLayerByName(name); // return Layer 图层对象 +``` + + +### removeLayer 移除 layer 图层 + +移除 layer 图层 + +```javascript +scene.removeLayer(layer); +``` + +参数 : + +- `layer` {Layer} + +### removeAllLayer() 移除所有的图层对象 + +移除所有的图层对象 + +```javascript +scene.removeAllLayer(); +``` + +## 控制组件方法 + +### addControl(ctl) 添加组件控件 + +添加组件控件 + +参数 : + +- `crl` { IControl } 用户创建的控件对象 + +```javascript +scene.addControl(ctl); +``` + +### removeControl(ctr) 移除用户添加的组件控件 + +移除用户添加的组件控件 + +参数 : + +- `ctl` { IControl } 用户创建的控件对象 + +```javascript +scene.removeControl(ctl); +``` + +### getControlByName(name) 根据控件的名称来获取控件 + +根据控件的名称来获取控件 + +- `name` { string } + + +```javascript +const zoomControl = new Zoom({ // zoom 控件 + name: 'z1', // 用户传入的控件名称(也可以不传入,该控件默认名称为 zoom) + position: 'topright' +}); + +scene.getControlByName('z1'); +``` + + +## 标记方法 + +### addMarker(maker) 添加标记 + +往场景中添加标记对象 + +参数 : + +- `maker` { IMarker } Marker 实例 + +```javascript +const marker = new Marker({ + element: el +}).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); +scene.addMarker(marker); +``` + +### addMarkerLayer(layer) 添加 Marker 统一管理图层 +当用户需要添加许多个 Marker 实例时,为了方便管理可以使用 markerLayer 对象统一管理 + +参数 : + +- `layer` { IMarkerLayer } 标记图层对象 + +```javascript +const markerLayer = new MarkerLayer(); +scene.addMarkerLayer(markerLayer); +``` +[示例地址](/zh/examples/point/marker#markerlayer) + +### removeMarkerLayer(layer) 移除标签图层 + +移除标签图层 + +参数 : + +- `layer` { IMarkerLayer } 标记图层对象 + +```javascript +scene.removeMarkerLayer(markerLayer); +``` + +### removeAllMakers() 移除场景中所有的标签对象 + +移除场景中所有的标签对象 + +```javascript +scene.removeAllMakers(); +``` + +## 地图方法 ### getZoom 获取缩放等级 @@ -178,29 +334,6 @@ scene.getZoom(); return {float}   当前缩放等级 -### getLayers() 获取所有图层 - -获取所有的地图图层 - -```javascript -scene.getLayers(); -``` - -### getLayerByName(name) 根据名称获取图层 - -根据图层名称获取图层 - -参数 - -- name {string} - -layer 初始化可配置图层 name - -```javascript -scene.getLayerByName(name); -``` - -return Layer 图层对象 ### getCenter() 获取地图中心 @@ -385,17 +518,6 @@ scene.fitBounds([ ]); ``` -### removeLayer 移除图层 - -移除 layer - -```javascript -scene.removeLayer(layer); -``` - -参数 - -- `layer` {Layer} ### exportMap 导出地图图片 @@ -411,9 +533,113 @@ scene.exportMap('png'); scene 销毁方法,离开页面,或者不需要使用地图可以调用 -``` +```javascript scene.destroy(); ``` +## iconfont 映射支持 + +### addIconFont(name, fontUnicode) 增加对数据中 unicode 的映射支持 + +支持对用户传入的数据进行 unicode 的映射,在内部维护一组名称和对应 key 的键值对 + +参数 : + +- `name` {string} +- `fontUnicode` {string} + +```javascript + scene.addIconFont("icon1", "") + scene.addIconFont("icon2", "") + scene.addFontFace(fontFamily, fontPath); + const pointIconFontLayer = new PointLayer({}) + .source( + [{ + j: 140, + w: 34, + m: 'icon1', + },{ + j: 140, + w: 36, + m: 'icon2', + }], + { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }, + ) + .shape('m', 'text') + .size(12) + .color('w', ['#f00', '#f00', '#0f0']) + .style({ + fontFamily, + iconfont: true, + textAllowOverlap: true, + }); + scene.addLayer(pointIconFontLayer); +``` + +### addIconFonts(options) 同时传入多组 name - unicode 的键值对 + +同时传入多组 name - unicode 的键值对 + +参数 : +- `options` { Array<[name, unicode]> } + +```javascript + scene.addIconFonts([ + ['icon1', ''], + ['icon2', ''], + ]); +``` +## 全局资源 + +### addImage(id, img) 全局中添加的图片资源 + +在 L7 的图层对象可以使用在 scene 全局中添加的图片资源 + +参数 : +- `id` {string} +- `img` {HTMLImageElement | File | string} +```javascript +scene.addImage('02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg'); +``` +[示例地址](/zh/examples/gallery/animate#animate_path_texture) + +### hasImage(id) 判断全局图片资源 + +判断是否已经在全局添加过相应的图片资源 + +参数 : +- `id` {string} +```javascript +scene.hasImage('imageID') +``` + +### removeImage(id) 全局删除图片资源 + +从全局删除对应的图片资源 + +参数 : +- `id` {string} +```javascript +scene.removeImage('imageID') +``` + +### addFontFace(fontFamily, fontPath) 添加字体文件 + +添加字体文件 + +参数 : +- `fontFamily` {string} 用户为自己定义的字体名称 +- `fontPath` {string} 导入的文件地址 +```javascript +let fontFamily = 'iconfont'; +let fontPath = '//at.alicdn.com/t/font_2534097_iiet9d3nekn.woff2?t=1620444089776'; +scene.addFontFace(fontFamily, fontPath); +``` ## 事件 diff --git a/docs/api/source/source.zh.md b/docs/api/source/source.zh.md index 32f786f7b0..baf8d161ea 100644 --- a/docs/api/source/source.zh.md +++ b/docs/api/source/source.zh.md @@ -7,7 +7,7 @@ order: 0 ## 概述 -source 地理数据处理模块,主要包含数据解析(parser),和数据处理(transform); +source 地理数据处理模块,主要包含数据解析(parser),和数据处理(transform) - data - option @@ -18,7 +18,7 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据 ### parser -不同数据类型处理成统一数据格式。矢量数据包括 GeoJON, CSV,Json 等不同数据格式,栅格数据,包括 Raster,Image 数据。将来还会支持瓦片格式数据。 +不同数据类型处理成统一数据格式。矢量数据包括 GeoJON, CSV,Json 等不同数据格式,栅格数据,包括 Raster,Image 数据。将来还会支持瓦片格式数据。 空间数据分矢量数据和栅格数据两大类 diff --git a/docs/common/layer/options.md b/docs/common/layer/options.md index 02541dbca6..6f51411cb8 100644 --- a/docs/common/layer/options.md +++ b/docs/common/layer/options.md @@ -16,11 +16,11 @@ ### minZoom _number_ **可选** _default:_ `0` -图层显示最小缩放等级,(0-18)   {number}  Mapbox (0-24) 高德 (3-18) +图层显示最小缩放等级,(0-18)   {number}  Mapbox (0-24) 高德 (2-19) ### maxZoom _number_ **可选** _default:_ `22` -图层显示最大缩放等级 (0-18)   {number}  Mapbox (0-24) 高德 (3-18) +图层显示最大缩放等级 (0-18)   {number}  Mapbox (0-24) 高德 (2-19) ### autoFit _bool_ **可选** _default:_ `false` diff --git a/examples/district/drill/demo/drill_down_view.js b/examples/district/drill/demo/drill_down_view.js index 439693e603..a65c91dde3 100644 --- a/examples/district/drill/demo/drill_down_view.js +++ b/examples/district/drill/demo/drill_down_view.js @@ -1,10 +1,10 @@ import { Scene } from '@antv/l7'; import { DrillDownLayer } from '@antv/l7-district'; -import { Mapbox } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; const colors = [ '#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70' ]; const scene = new Scene({ id: 'map', - map: new Mapbox({ + map: new GaodeMap({ center: [ 116.2825, 39.9 ], pitch: 0, style: 'blank', diff --git a/examples/district/drill/demo/meta.json b/examples/district/drill/demo/meta.json index 7c68a4fcd8..3c10c08c63 100644 --- a/examples/district/drill/demo/meta.json +++ b/examples/district/drill/demo/meta.json @@ -9,6 +9,16 @@ "title": "中国地图钻取", "screenshot": "https://gw.alipayobjects.com/mdn/rms_8e1672/afts/img/A*xjjARqU70xoAAAAAAAAAAABkARQnAQ" }, + { + "filename": "drill_down_view.js", + "title": "中国地图钻取", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*KphnSq_0C6sAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "drill_down_province.js", + "title": "省级地图钻取", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*fVHISrzrz44AAAAAAAAAAAAAARQnAQ" + }, { "filename": "drill_down_bubble.js", "title": "中国地图钻取气泡图", diff --git a/examples/district/react/demo/province.tsx b/examples/district/react/demo/province.tsx index 2b1aa58fb3..d41202f8f5 100644 --- a/examples/district/react/demo/province.tsx +++ b/examples/district/react/demo/province.tsx @@ -203,7 +203,7 @@ class Province extends React.Component { }); const scene = new Scene({ id: 'map', - map: new Mapbox({ + map: new GaodeMap({ center: [116.2825, 39.9], pitch: 0, style: 'blank', diff --git a/examples/gallery/animate/demo/animate_path_texture.js b/examples/gallery/animate/demo/animate_path_texture.js new file mode 100644 index 0000000000..72d2284bf9 --- /dev/null +++ b/examples/gallery/animate/demo/animate_path_texture.js @@ -0,0 +1,40 @@ +import { Scene, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [ 120.19382669582967, 30.258134 ], + pitch: 0, + zoom: 16, + style: 'dark' + }) +}); +scene.on('loaded', () => { + scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + ); + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json' + ) + .then(res => res.json()) + .then(data => { + const layer = new LineLayer() + .source(data) + .size(4) + .shape('line') + .texture('02') + .color('#25d8b7') + .animate({ + interval: 1, // 间隔 + duration: 1, // 持续时间,延时 + trailLength: 2 // 流线长度 + }) + .style({ + lineTexture: true, // 开启线的贴图功能 + iconStep: 100, // 设置贴图纹理的间距 + }) + scene.addLayer(layer); + }); +}); diff --git a/examples/gallery/animate/demo/build.js b/examples/gallery/animate/demo/build.js index d705f55c73..10424c5a47 100644 --- a/examples/gallery/animate/demo/build.js +++ b/examples/gallery/animate/demo/build.js @@ -4,7 +4,7 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - style: 'amap://styles/a49ef8d081db7b85adb2e90ba7941f1e?isPublic=true', + style: 'dark', center: [ 120.173104, 30.244072 ], pitch: 70.41138037735848, zoom: 17.18, diff --git a/examples/gallery/animate/demo/meta.json b/examples/gallery/animate/demo/meta.json index 7a326cd872..c17d654ee2 100644 --- a/examples/gallery/animate/demo/meta.json +++ b/examples/gallery/animate/demo/meta.json @@ -4,6 +4,11 @@ "en": "Gallery" }, "demos": [ + { + "filename": "animate_path_texture.js", + "title": "路径贴图", + "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*TLt7RI9bAWMAAAAAAAAAAAAAARQnAQ" + }, { "filename": "animate_path.js", "title": "路径动画", diff --git a/examples/line/animate/demo/meta.json b/examples/line/animate/demo/meta.json index fe382753ee..b082eb808d 100644 --- a/examples/line/animate/demo/meta.json +++ b/examples/line/animate/demo/meta.json @@ -4,6 +4,11 @@ "en": "line" }, "demos": [ + { + "filename": "wind.js", + "title": "风场弧线", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*LpcBTKiazZcAAAAAAAAAAAAAARQnAQ" + }, { "filename": "arcCircle.js", "title": "大圆弧线", diff --git a/examples/line/animate/demo/wind.js b/examples/line/animate/demo/wind.js new file mode 100644 index 0000000000..b17f2afa67 --- /dev/null +++ b/examples/line/animate/demo/wind.js @@ -0,0 +1,41 @@ +import { Scene, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 0, + style: 'light', + center: [ 60, 40.7128 ], + zoom: 2 + }) +}); +scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/7455fead-1dc0-458d-b91a-fb4cf99e701e.txt' + ) + .then(res => res.text()) + .then(data => { + const layer = new LineLayer({ blend: 'normal' }) + .source(data, + { + parser: { + type: 'csv', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2' + } + }) + .size(1) + .shape('arc') + .color('#6495ED') + .animate({ + duration: 4, + interval: 0.2, + trailLength: 0.6 + }); + // .forward(false) + scene.addLayer(layer); + }); +}); diff --git a/examples/line/path/demo/meta.json b/examples/line/path/demo/meta.json index b9c242aeb0..00b1b96403 100644 --- a/examples/line/path/demo/meta.json +++ b/examples/line/path/demo/meta.json @@ -16,14 +16,19 @@ }, { "filename": "road_light.js", - "title": "路径", + "title": "路径light", "screenshot":"https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*LuXiTZAq_84AAAAAAAAAAABkARQnAQ" }, { "filename": "road_dark.js", - "title": "路径", + "title": "路径dark", "screenshot":"https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*DDjQRLEnwpoAAAAAAAAAAABkARQnAQ" }, + { + "filename": "road_red.js", + "title": "路径2d", + "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*1cF2RYwkcq8AAAAAAAAAAAAAARQnAQ" + }, { "filename": "road_dark_dash.js", "title": "路径虚线", diff --git a/examples/line/path/demo/road_red.js b/examples/line/path/demo/road_red.js new file mode 100644 index 0000000000..a7a5725614 --- /dev/null +++ b/examples/line/path/demo/road_red.js @@ -0,0 +1,33 @@ +import { + Scene, + LineLayer +} from '@antv/l7'; +import { + GaodeMap +} from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [116.3956, 39.9392], + pitch: 0, + zoom: 10, + rotation: 0, + style: 'amap://styles/light', + viewMode: '2D', + }) +}); +scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/0d2f0113-f48b-4db9-8adc-a3937243d5a3.json' + ) + .then(res => res.json()) + .then(data => { + const layer = new LineLayer({}) + .source(data) + .size(1.5) + .shape('line') + .color('标准名称', [ '#5B8FF9', '#5CCEA1', '#5D7092' ]); + scene.addLayer(layer); + }); +}); diff --git a/examples/point/image/demo/meta.json b/examples/point/image/demo/meta.json index e9007e448f..6e6731ba2c 100644 --- a/examples/point/image/demo/meta.json +++ b/examples/point/image/demo/meta.json @@ -18,6 +18,11 @@ "filename": "weather.js", "title": "天气", "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*-nk1RZJeGooAAAAAAAAAAABkARQnAQ" + }, + { + "filename": "road.js", + "title": "路线图", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*2HLeQ4AjxacAAAAAAAAAAAAAARQnAQ" } ] } diff --git a/examples/point/image/demo/road.js b/examples/point/image/demo/road.js new file mode 100644 index 0000000000..c4df662595 --- /dev/null +++ b/examples/point/image/demo/road.js @@ -0,0 +1,106 @@ +import { Scene, LineLayer, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.115, 30.221], + pitch: 40, + zoom: 16, + viewMode: '3D', + }) +}); +scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json', + ) + .then((res) => res.json()) + .then((data) => { + + scene.addImage( + 'road', + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*haGlTpW2BQgAAAAAAAAAAAAAARQnAQ' + ); + + const layer = new LineLayer() + .source(data) + .size(8) + .shape('line') + .texture('road') + .color('rgb(20, 180, 90)') + .animate({ + interval: 1, // 间隔 + duration: 1, // 持续时间,延时 + trailLength: 2, // 流线长度 + }) + .style({ + lineTexture: true, // 开启线的贴图功能 + iconStep: 200, // 设置贴图纹理的间距 + }); + scene.addLayer(layer); + + scene.addImage( + 'start', + 'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg', + ); + scene.addImage( + 'visitor', + 'https://gw.alipayobjects.com/zos/bmw-prod/64db255d-b636-4929-b072-068e75178b23.svg', + ); + scene.addImage( + 'museum', + 'https://gw.alipayobjects.com/zos/bmw-prod/0630591d-64db-4057-a04d-d65f43aebf0f.svg', + ); + scene.addImage( + 'supermarket', + 'https://gw.alipayobjects.com/zos/bmw-prod/ab42799d-dea6-4d37-bd62-3ee3e06bf6c0.svg', + ); + scene.addImage( + 'tower', + 'https://gw.alipayobjects.com/zos/bmw-prod/6d27cf89-638c-432b-a8c4-cac289ee98a8.svg', + ); + scene.addImage( + 'end', + 'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg', + ); + const imageLayer = new PointLayer() + .source([{ + lng: 120.11025885601617, + lat: 30.22006389085372, + icon: 'start' + },{ + lng: 120.11123578376913, + lat: 30.220443561196277, + icon: 'visitor' + },{ + lng: 120.11408457779198, + lat: 30.22019805564678, + icon: 'museum' + },{ + lng: 120.11683172384723, + lat: 30.21875509667716, + icon: 'supermarket' + },{ + lng: 120.11945546294194, + lat: 30.218724022876376, + icon: 'tower' + },{ + lng: 120.1184189041221, + lat: 30.21783201718256, + icon: 'end' + } + ], { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('icon', ['start', 'visitor', 'museum', 'supermarket', 'tower', 'end']) + .size(35) + .style({ + offsets: [0, 20] + }) + scene.addLayer(imageLayer); + }); +}); \ No newline at end of file diff --git a/examples/point/scatter/demo/animatePoint.js b/examples/point/scatter/demo/animatePoint.js new file mode 100644 index 0000000000..2d5171bb57 --- /dev/null +++ b/examples/point/scatter/demo/animatePoint.js @@ -0,0 +1,54 @@ +import { Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'light', + center: [112, 23.69], + zoom: 2.5, + }) +}); + +fetch( + 'https://gw.alipayobjects.com/os/basement_prod/9078fd36-ce8d-4ee2-91bc-605db8315fdf.csv', +) + .then((res) => res.text()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data, { + parser: { + type: 'csv', + x: 'Longitude', + y: 'Latitude', + }, + }) + .shape('circle') + .active(true) + .animate(true) + .size(40) + .color('#ffa842') + .style({ + opacity: 1, + offsets: [40, 40], + }); + const pointLayer2 = new PointLayer({}) + .source(data, { + parser: { + type: 'csv', + x: 'Longitude', + y: 'Latitude', + }, + }) + .shape('circle') + .active(true) + .animate(true) + .size(50) + .color('#f00') + .style({ + opacity: 1, + }); + + scene.addLayer(pointLayer); + scene.addLayer(pointLayer2); + }); diff --git a/examples/point/scatter/demo/dynamicScatter.js b/examples/point/scatter/demo/dynamicScatter.js new file mode 100644 index 0000000000..ff7f0c0e89 --- /dev/null +++ b/examples/point/scatter/demo/dynamicScatter.js @@ -0,0 +1,52 @@ +import { Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'light', + center: [120.19382669582967, 30.258134], + zoom: 10 + }) +}); + +const radius = 0.1; + +function pointOnCircle(angle) { + return { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Point', + coordinates: [ + 120.19382669582967 + Math.cos(angle) * radius, + 30.258134 + Math.sin(angle) * radius, + ], + }, + }, + ], + }; +} +const layer = new PointLayer({}) + .source(pointOnCircle(0)) + .shape('circle') + .size(15) // default 1 + .active(false) + .color('#2F54EB') + .style({ + stroke: '#fff', + strokeWidth: 2, + opacity: 1, + }); +scene.addLayer(layer); +layer.setData(pointOnCircle(1000)); + +function animateMarker(timestamp) { + layer.setData(pointOnCircle(timestamp / 1000)); + scene.render(); + requestAnimationFrame(animateMarker); +} +animateMarker(0); \ No newline at end of file diff --git a/examples/point/scatter/demo/meta.json b/examples/point/scatter/demo/meta.json index 27d083e3d6..ea56c67d70 100644 --- a/examples/point/scatter/demo/meta.json +++ b/examples/point/scatter/demo/meta.json @@ -8,8 +8,16 @@ "filename": "scatter.js", "title": "散点图", "screenshot":"https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*LnlmQ7sFWigAAAAAAAAAAABkARQnAQ" - + }, + { + "filename": "dynamicScatter.js", + "title": "动态散点", + "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*iourTIHnDk0AAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "animatePoint.js", + "title": "水波散点", + "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*BsEnTrJ5JRcAAAAAAAAAAAAAARQnAQ" } - ] } diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js new file mode 100644 index 0000000000..80842e25e8 --- /dev/null +++ b/examples/point/text/demo/iconfont.js @@ -0,0 +1,77 @@ +import { Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [ 110, 36 ], + pitch: 0, + style: 'light', + zoom: 3 + }) +}); +let fontFamily = 'iconfont'; +let fontPath = '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; +scene.addFontFace(fontFamily, fontPath); +scene.addIconFont("icon1", "") + +scene.on('loaded', () => { + fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') + .then(res => res.json()) + .then(data => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w' + } + }) + .shape('m', 'text') + .size(12) + // .rotate("j",()=>{ + // return Math.random()*3*(Math.random()>0.5?1:-1) + // }) + .color('w', [ '#0e0030', '#0e0030', '#0e0030' ]) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ 0, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0 + }); + + scene.addLayer(pointLayer); + }); + + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('icon', 'text') + .size(12) + .color('w', ['#f00', '#f00', '#0f0']) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [-10, 0], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + fontFamily, + iconfont: true, + // textAllowOverlap: true, + }); + scene.addLayer(pointLayer); + }) +}); diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js new file mode 100644 index 0000000000..d4365206ab --- /dev/null +++ b/examples/point/text/demo/iconfonts.js @@ -0,0 +1,225 @@ +import { Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.5, 30.2], + pitch: 0, + style: 'light', + zoom: 8.5, + zooms: [8, 10], + viewMode: '2D' + }), +}); +let originData = [ + { + lng: 120, + lat: 30, + iconType: 'sun', + iconColor: "#FFA500", + backgoundColor: "#00BFFF", + temperature: '28℃', + weather: '晴朗' + }, + { + lng: 120.2, + lat: 30.5, + iconType: 'sun', + iconColor: "#FFA500", + backgoundColor: "#00BFFF", + temperature: '28℃', + weather: '晴朗' + }, + { + lng: 121.5, + lat: 31.4, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120, + lat: 31, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120.6, + lat: 30.8, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120.5, + lat: 31.3, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 121.3, + lat: 30.2, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 121, + lat: 30.5, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 120.6, + lat: 30, + iconType: 'middleRain', + iconColor: "#6495ED", + backgoundColor: "#326EA0", + temperature: '24℃', + weather: '中雨' + }, + { + lng: 120.2, + lat: 29.7, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 121.7, + lat: 29.8, + iconType: 'middleRain', + iconColor: "#6495ED", + backgoundColor: "#326EA0", + temperature: '24℃', + weather: '中雨' + }, + { + lng: 121.5, + lat: 30, + iconType: 'hugeRain', + iconColor: "#4678D2", + backgoundColor: "#285A8C", + temperature: '20℃', + weather: '大雨' + }, +]; +let fontFamily = 'iconfont'; +let fontPath = '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076'; +scene.addFontFace(fontFamily, fontPath); +scene.addIconFonts([ + ['smallRain', ''], + ['middleRain', ''], + ['hugeRain', ''], + ['sun', ''], + ['cloud', ''], +]); + +scene.on('loaded', () => { + + const layer = new PointLayer() + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('circle') + .color('backgoundColor') + .size(40) + scene.addLayer(layer); + + + const pointIconFontLayer = new PointLayer({}) + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + } + }, + ) + .shape('iconType', 'text') + .size(30) + .color('iconColor') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [38, 10], // 文本相对锚点的偏移量 [水平, 垂直] + fontFamily, + iconfont: true, + textAllowOverlap: true, + }); + scene.addLayer(pointIconFontLayer); + + const textLayer = new PointLayer({}) + .source(originData, + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .shape('temperature', 'text') + .size(10) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [5, -55], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: "Times New Roman", + textAllowOverlap: true, + }); + scene.addLayer(textLayer); + + const textLayer2 = new PointLayer({}) + .source(originData, + { + parser: { + type: 'json', + x: 'lng', + y: 'lat' + }, + }, + ) + .shape('weather', 'text') + .size(14) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [5, -15], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: "Times New Roman", + textAllowOverlap: true, + }); + scene.addLayer(textLayer2); + +}); diff --git a/examples/point/text/demo/meta.json b/examples/point/text/demo/meta.json index 603cfec008..981ce924ef 100644 --- a/examples/point/text/demo/meta.json +++ b/examples/point/text/demo/meta.json @@ -9,11 +9,25 @@ "title": "点数据标注", "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*7blvQ4v7Q1UAAAAAAAAAAABkARQnAQ" }, + { + "filename": "iconfont.js", + "title": "文字图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*96iHTKybWYcAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "iconfonts.js", + "title": "天气图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*AouOQ4VYTJMAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "temperture.js", + "title": "气温图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*VFmxTqQc7v4AAAAAAAAAAAAAARQnAQ" + }, { "filename": "polygon_text.js", "title": "面数据标注", "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*rCFqRp3iQosAAAAAAAAAAABkARQnAQ" } - ] } diff --git a/examples/point/text/demo/point_text.js b/examples/point/text/demo/point_text.js index 6a2455e51a..79bd2d2100 100644 --- a/examples/point/text/demo/point_text.js +++ b/examples/point/text/demo/point_text.js @@ -4,7 +4,7 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [ 120.19382669582967, 30.258134 ], + center: [ 110, 36 ], pitch: 0, style: 'light', zoom: 3 @@ -40,4 +40,5 @@ scene.on('loaded', () => { scene.addLayer(pointLayer); }); + }); diff --git a/examples/point/text/demo/temperture.js b/examples/point/text/demo/temperture.js new file mode 100644 index 0000000000..487071489f --- /dev/null +++ b/examples/point/text/demo/temperture.js @@ -0,0 +1,103 @@ +import { Scene, PointLayer, PolygonLayer, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'dark', + pitch: 40, + center: [118.8, 32.056], + zoom: 12.5 + }) +}); +let fontFamily = 'iconfont'; +let fontPath = + '//at.alicdn.com/t/font_2534097_x6rsov3i1g.woff2?t=1622107341225'; + scene.addIconFont("icon", "") + scene.addFontFace(fontFamily, fontPath); + +let colors = [ + '#87CEFA', + '#00BFFF', + + '#7FFFAA', + '#00FF7F', + '#32CD32', + + '#F0E68C', + '#FFD700', + + '#FF7F50', + '#FF6347', + '#FF0000' +] + +scene.on('loaded', () => { + fetch('https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json') + .then((res) => res.json()) + .then((data) => { + + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3, + }) + .source(data) + .shape('fill') + .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) + .style({ + opacity: 0.8 + }) + scene.addLayer(filllayer); + + const linelayer = new LineLayer({ + zIndex: 5, + name: 'line2', + }) + .source(data) + .shape('line') + .size(1) + .color('#fff') + .style({ + opacity: 0.3 + }); + scene.addLayer(linelayer); + + const pointLayer = new PointLayer({ + zIndex: 10 + }) + .source(data) + .shape('icon', 'text') + .size(30) + .color('count', t => { + let c = Number(t.replace('℃', '')) + return colors[Math.floor(((c - 18)/16)*10)] + }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [30, 5], + padding: [2, 2], + fontFamily, + iconfont: true, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + + const tempertureLayer = new PointLayer({ + zIndex: 10 + }) + .source(data) + .shape('count', 'text') + .size(12) + .color('count', t => { + let c = Number(t.replace('℃', '')) + return colors[Math.floor(((c - 18)/16)*10)] + }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [35, 30], + padding: [1, 1], + }); + scene.addLayer(tempertureLayer); + + }) +}); diff --git a/examples/react/covid/index.zh.md b/examples/react/covid/index.zh.md index 09f8599575..a4bb66bfc3 100644 --- a/examples/react/covid/index.zh.md +++ b/examples/react/covid/index.zh.md @@ -1,5 +1,5 @@ --- -title: COVID-19 地图 +title: COVID-19(新冠肺炎)地图 order: 0 --- [![github](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Nk9mQ48ZoZMAAAAAAAAAAABkARQnAQ)](https://github.com/antvis/L7) diff --git a/examples/react/layer/demo/Point_image.tsx b/examples/react/layer/demo/Point_image.tsx index 87db3ae535..790281bedb 100644 --- a/examples/react/layer/demo/Point_image.tsx +++ b/examples/react/layer/demo/Point_image.tsx @@ -42,13 +42,15 @@ const World = React.memo(function Map() { options={{ autoFit: true, }} + source={{ data, + // @ts-ignore parser: { type: 'json', x: 'longitude', y: 'latitude', - }, + } }} shape={{ field: 'name', diff --git a/examples/react/layer/demo/meta.json b/examples/react/layer/demo/meta.json index 4c4a4c1f8d..0a37f027cf 100644 --- a/examples/react/layer/demo/meta.json +++ b/examples/react/layer/demo/meta.json @@ -6,8 +6,8 @@ "demos": [ { "filename": "Point_image.tsx", - "title": "点标注图", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_855bab/afts/img/A*HQShTKuKq6wAAAAAAAAAAABkARQnAQ" + "title": "图片标注图", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*w-8iQpR1NEQAAAAAAAAAAAAAARQnAQ" }, { "filename": "marker.tsx", @@ -18,6 +18,6 @@ "filename": "popup.tsx", "title": "信息窗", "screenshot": "https://gw.alipayobjects.com/mdn/rms_855bab/afts/img/A*RWngRL7rZKQAAAAAAAAAAAAAARQnAQ" - }, + } ] } diff --git a/examples/react/layer/demo/popup.tsx b/examples/react/layer/demo/popup.tsx index a5ff066d93..a3c38021d0 100644 --- a/examples/react/layer/demo/popup.tsx +++ b/examples/react/layer/demo/popup.tsx @@ -96,6 +96,7 @@ const World = React.memo(function Map() { {popupInfo && ( diff --git a/examples/tutorial/layer/demo/mapbox.js b/examples/tutorial/layer/demo/mapbox.js deleted file mode 100644 index 63daeb5080..0000000000 --- a/examples/tutorial/layer/demo/mapbox.js +++ /dev/null @@ -1,17 +0,0 @@ -import { Scale, Zoom, Scene } from '@antv/l7'; -import { Mapbox } from '@antv/l7-maps'; -const scene = new Scene({ - id: 'map', - map: new Mapbox({ - style: 'light', - pitch: 0, - center: [ 107.054293, 35.246265 ], - zoom: 4.056 - }) -}); -scene.on('loaded', () => { - const zoomControl = new Zoom(); - const scaleControl = new Scale(); - scene.addControl(zoomControl); - scene.addControl(scaleControl); -}); diff --git a/examples/tutorial/layer/demo/meta.json b/examples/tutorial/layer/demo/meta.json index 7e0fad15f0..cffc15ca37 100644 --- a/examples/tutorial/layer/demo/meta.json +++ b/examples/tutorial/layer/demo/meta.json @@ -5,14 +5,9 @@ }, "demos": [ { - "filename": "amap.js", - "title": "高德底图组件", - "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*yXzQRYcGTyoAAAAAAAAAAABkARQnAQ" - }, - { - "filename": "mapbox.js", - "title": "MapBox底图组件", - "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ" + "filename": "layer_highlight.js", + "title": "交互高亮图层", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*jBzZRp_umUoAAAAAAAAAAAAAARQnAQ" } ] } diff --git a/examples/tutorial/map/demo/amapInstance.js b/examples/tutorial/map/demo/amapInstance.js index 44dfac37e2..bba1e2154b 100644 --- a/examples/tutorial/map/demo/amapInstance.js +++ b/examples/tutorial/map/demo/amapInstance.js @@ -52,7 +52,8 @@ window.onLoad = function() { }); }; -const url = 'https://webapi.amap.com/maps?v=1.4.15&key=15cd8a57710d40c9b7c0e3cc120f1200&callback=onLoad'; +// const url = 'https://webapi.amap.com/maps?v=1.4.15&key=15cd8a57710d40c9b7c0e3cc120f1200&callback=onLoad'; +const url = 'https://webapi.amap.com/maps?v=2.0&key=ff533602d57df6f8ab3b0fea226ae52f&callback=onLoad'; const jsapi = document.createElement('script'); jsapi.charset = 'utf-8'; jsapi.src = url; diff --git a/examples/tutorial/map/demo/amapInstance2d.js b/examples/tutorial/map/demo/amapInstance2d.js new file mode 100644 index 0000000000..fea16b06bc --- /dev/null +++ b/examples/tutorial/map/demo/amapInstance2d.js @@ -0,0 +1,58 @@ +import { Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +window.onLoad = function() { + const map = new AMap.Map('map', { + pitch: 0, + mapStyle: 'amap://styles/darkblue', + center: [ 121.435159, 31.256971 ], + zoom: 14.89, + minZoom: 10 + }); + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + mapInstance: map + }) + }); + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json' + ) + .then(res => res.json()) + .then(data => { + const pointLayer = new PointLayer() + .source(data, { + parser: { + type: 'json', + x: 'longitude', + y: 'latitude' + } + }) + .shape('name', [ + 'circle', + 'triangle', + 'square', + 'pentagon', + 'hexagon', + 'octogon', + 'hexagram', + 'rhombus', + 'vesica' + ]) + .size('unit_price', [ 10, 25 ]) + .color('name', [ '#5B8FF9', '#5CCEA1', '#5D7092', '#F6BD16', '#E86452' ]) + .style({ + opacity: 0.3, + strokeWidth: 2 + }); + scene.addLayer(pointLayer); + }); + }); +}; + +const url = 'https://webapi.amap.com/maps?v=2.0&key=ff533602d57df6f8ab3b0fea226ae52f&callback=onLoad'; +const jsapi = document.createElement('script'); +jsapi.charset = 'utf-8'; +jsapi.src = url; +document.head.appendChild(jsapi); diff --git a/examples/tutorial/map/demo/meta.json b/examples/tutorial/map/demo/meta.json index 329fc51eb9..6fdf9ebc55 100644 --- a/examples/tutorial/map/demo/meta.json +++ b/examples/tutorial/map/demo/meta.json @@ -17,7 +17,12 @@ { "filename": "amapInstance.js", "title": "通过高德地图实例化", - "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*C5d2RJ08hOkAAAAAAAAAAAAAARQnAQ" + }, + { + "filename": "amapInstance2d.js", + "title": "通过高德地图实例化(2d)", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*C5d2RJ08hOkAAAAAAAAAAAAAARQnAQ" } ] } diff --git a/gatsby-config.js b/gatsby-config.js index 0e1cdc8230..04116c9b81 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -268,7 +268,7 @@ module.exports = { } ], playground: { - container: '
', + container: '
', dependencies: { '@antv/l7': 'latest', '@antv/l7-maps': 'latest' diff --git a/packages/component/src/control/BaseControl.ts b/packages/component/src/control/BaseControl.ts index 4f61dcee19..378c583d5c 100644 --- a/packages/component/src/control/BaseControl.ts +++ b/packages/component/src/control/BaseControl.ts @@ -44,7 +44,7 @@ export default class Control extends EventEmitter { name: `${controlId++}`, }; } - public setPosition(position: PositionName) { + public setPosition(position: PositionName = 'bottomright') { // 考虑组件的自动布局,需要销毁重建 const controlService = this.controlService; if (controlService) { diff --git a/packages/component/src/css/l7.css b/packages/component/src/css/l7.css index 7199630953..850a9139a1 100644 --- a/packages/component/src/css/l7.css +++ b/packages/component/src/css/l7.css @@ -474,5 +474,3 @@ .amap-logo{ display: none !important; } - - diff --git a/packages/component/src/marker.ts b/packages/component/src/marker.ts index 864324a492..9f04045e68 100644 --- a/packages/component/src/marker.ts +++ b/packages/component/src/marker.ts @@ -56,7 +56,8 @@ export default class Marker extends EventEmitter { // this.sceneSerive.getSceneContainer().appendChild(element as HTMLElement); this.mapsService.getMarkerContainer().appendChild(element as HTMLElement); this.registerMarkerEvent(element as HTMLElement); - this.mapsService.on('camerachange', this.update); + this.mapsService.on('camerachange', this.update); // 注册高德1.x 的地图事件监听 + this.mapsService.on('viewchange', this.update); // 注册高德2.0 的地图事件监听 this.update(); this.added = true; this.emit('added'); diff --git a/packages/core/src/services/asset/FontService.ts b/packages/core/src/services/asset/FontService.ts index 0bbc92e43d..b1eb47ddab 100644 --- a/packages/core/src/services/asset/FontService.ts +++ b/packages/core/src/services/asset/FontService.ts @@ -32,6 +32,7 @@ const VALID_PROPS = [ 'cutoff', 'radius', ]; + function getDefaultCharacterSet() { const charSet = []; for (let i = 32; i < 128; i++) { @@ -51,6 +52,7 @@ function setTextStyle( ctx.textBaseline = 'middle'; // ctx.textAlign = 'left'; } + function populateAlphaChannel(alphaChannel: number[], imageData: ImageData) { // populate distance value from tinySDF to image alpha channel for (let i = 0; i < alphaChannel.length; i++) { @@ -60,7 +62,23 @@ function populateAlphaChannel(alphaChannel: number[], imageData: ImageData) { @injectable() export default class FontService implements IFontService { + public get scale() { + return HEIGHT_SCALE; + } + + public get canvas(): HTMLCanvasElement { + const data = this.cache.get(this.key); + return data && data.data; + } + + public get mapping(): IFontMapping { + const data = this.cache.get(this.key); + return data && data.mapping; + } public fontAtlas: IFontAtlas; + + // iconFontMap 记录用户设置的 iconfont unicode 和名称的键值关系 + public iconFontMap: Map; private iconFontGlyphs: { [key: string]: string; } = {}; @@ -79,46 +97,52 @@ export default class FontService implements IFontService { sdf: true, cutoff: DEFAULT_CUTOFF, radius: DEFAULT_RADIUS, + iconfont: false, }; this.key = ''; + this.iconFontMap = new Map(); } public addIconGlyphs(glyphs: IIconFontGlyph[]): void { glyphs.forEach((glyph) => { this.iconFontGlyphs[glyph.name] = glyph.unicode; }); } + + /** + * 添加对 iconfont unicode 的映射 + * @param fontUnicode + * @param name + */ + public addIconFont(name: string, fontUnicode: string): void { + this.iconFontMap.set(name, fontUnicode); + } + + /** + * 获取自定义 iconfont 别称对应的 unicode 编码,若是当前的 map 中没有对应的键值对,那么就返回原值 + * @param name + * @returns + */ + public getIconFontKey(name: string): string { + return this.iconFontMap.get(name) || name; + } + public getGlyph(name: string): string { if (this.iconFontGlyphs[name]) { return String.fromCharCode(parseInt(this.iconFontGlyphs[name], 16)); } return ''; } - public get scale() { - return HEIGHT_SCALE; - } - - public get canvas(): HTMLCanvasElement { - const data = this.cache.get(this.key); - return data && data.data; - } - - public get mapping(): IFontMapping { - const data = this.cache.get(this.key); - return data && data.mapping; - } public setFontOptions(option: Partial) { this.fontOptions = { ...this.fontOptions, ...option, }; - // const oldKey = this.key; this.key = this.getKey(); const charSet = this.getNewChars(this.key, this.fontOptions.characterSet); const cachedFontAtlas = this.cache.get(this.key); - if (cachedFontAtlas && charSet.length === 0) { // update texture with cached fontAtlas return; @@ -137,6 +161,7 @@ export default class FontService implements IFontService { public destroy(): void { this.cache.clear(); + this.iconFontMap.clear(); } private generateFontAtlas( @@ -152,6 +177,7 @@ export default class FontService implements IFontService { sdf, radius, cutoff, + iconfont, } = this.fontOptions; let canvas = cachedFontAtlas && cachedFontAtlas.data; if (!canvas) { @@ -197,7 +223,22 @@ export default class FontService implements IFontService { // tinySDF.size equals `fontSize + buffer * 2` const imageData = ctx.getImageData(0, 0, tinySDF.size, tinySDF.size); for (const char of characterSet) { - populateAlphaChannel(tinySDF.draw(char), imageData); + if (iconfont) { + // @ts-ignore + // const icon = eval( + // '("' + char.replace('&#x', '\\u').replace(';', '') + '")', + // ); + + const icon = String.fromCharCode( + parseInt(char.replace('&#x', '').replace(';', ''), 16), + ); + const iconData = tinySDF.draw(icon); + populateAlphaChannel(iconData, imageData); + } else { + populateAlphaChannel(tinySDF.draw(char), imageData); + } + // populateAlphaChannel(tinySDF.draw(char), imageData); + // 考虑到描边,需要保留 sdf 的 buffer,不能像 deck.gl 一样直接减去 ctx.putImageData(imageData, mapping[char].x, mapping[char].y); } @@ -221,6 +262,7 @@ export default class FontService implements IFontService { } private getKey() { + return 'key'; const { fontFamily, fontWeight, @@ -231,11 +273,18 @@ export default class FontService implements IFontService { cutoff, } = this.fontOptions; if (sdf) { - return `${fontFamily} ${fontWeight} ${fontSize} ${buffer} ${radius} ${cutoff}`; + return `${fontFamily} ${fontWeight} ${fontSize} ${buffer} ${radius} ${cutoff} `; } return `${fontFamily} ${fontWeight} ${fontSize} ${buffer}`; } + /** + * + * @param key + * @param characterSet + * @returns + * 若是相同的 key,那么将字符存储到同同一个字符列表中 + */ private getNewChars(key: string, characterSet: string[]): string[] { const cachedFontAtlas = this.cache.get(key); if (!cachedFontAtlas) { diff --git a/packages/core/src/services/asset/IFontService.ts b/packages/core/src/services/asset/IFontService.ts index 19806a3677..83a688fd0a 100644 --- a/packages/core/src/services/asset/IFontService.ts +++ b/packages/core/src/services/asset/IFontService.ts @@ -7,6 +7,7 @@ export interface IFontOptions { sdf: boolean; cutoff: number; radius: number; + iconfont: boolean; } export interface IFontMappingOption { characterSet: string[]; @@ -29,6 +30,10 @@ export interface IFontMapping { [key: string]: IFontMappingItem; [key: number]: IFontMappingItem; } + +export interface IFontIconFontMapItem { + [key: string]: string; +} export interface IFontAtlas { xOffset: number; yOffset: number; @@ -44,11 +49,14 @@ export interface IIconFontGlyph { } export interface IFontService { mapping: IFontMapping; + iconFontMap: Map; fontAtlas: IFontAtlas; canvas: HTMLCanvasElement; scale: number; init(): void; addIconGlyphs(glyphs: IIconFontGlyph[]): void; + addIconFont(name: string, fontUnicode: string): void; + getIconFontKey(name: string): string; getGlyph(name: string): string; setFontOptions(option: Partial): void; destroy(): void; diff --git a/packages/core/src/services/asset/IconService.ts b/packages/core/src/services/asset/IconService.ts index b2f6f17a7f..64af149627 100644 --- a/packages/core/src/services/asset/IconService.ts +++ b/packages/core/src/services/asset/IconService.ts @@ -1,3 +1,5 @@ +// @ts-ignore +import TinySDF from '@mapbox/tiny-sdf'; import { EventEmitter } from 'eventemitter3'; import { inject, injectable } from 'inversify'; import { TYPES } from '../../types'; @@ -96,6 +98,9 @@ export default class IconService extends EventEmitter implements IIconService { } } + /** + * 将新增的 icon 图像存储到画布上(正方形) + */ private updateIconAtlas() { this.canvas.width = MAX_CANVAS_WIDTH; this.canvas.height = this.canvasHeight; @@ -117,6 +122,9 @@ export default class IconService extends EventEmitter implements IIconService { }); } + /** + * 计算 icon 在画布上的排布(是否需要换行) + */ private updateIconMap() { const { mapping, canvasHeight } = buildIconMaping( this.iconData, diff --git a/packages/core/src/services/camera/CameraService.ts b/packages/core/src/services/camera/CameraService.ts index 7b885e060e..5ed1c415c3 100644 --- a/packages/core/src/services/camera/CameraService.ts +++ b/packages/core/src/services/camera/CameraService.ts @@ -24,7 +24,8 @@ export default class CameraService implements ICameraService { /** * ViewMatrix 逆矩阵,用于计算相机位置 */ - private viewMatrixInverse: number[]; + // private viewMatrixInverse: number[]; + private viewMatrixInverse: mat4; /** * 相机位置 @@ -42,10 +43,12 @@ export default class CameraService implements ICameraService { this.viewport = viewport; // 计算逆矩阵 - this.viewMatrixInverse = (mat4.invert( - mat4.create(), - (this.getViewMatrix() as unknown) as mat4, - ) as unknown) as number[]; + // this.viewMatrixInverse = (mat4.invert( + // mat4.create(), (this.getViewMatrix() as unknown) as mat4, + // ) as unknown) as number[]; + + this.viewMatrixInverse = mat4.create(); + mat4.invert(this.viewMatrixInverse, viewport.getViewMatrix() as mat4); this.cameraPosition = [ this.viewMatrixInverse[12], diff --git a/packages/core/src/services/config/ConfigService.ts b/packages/core/src/services/config/ConfigService.ts index 5ccde0eb48..e450237e5d 100644 --- a/packages/core/src/services/config/ConfigService.ts +++ b/packages/core/src/services/config/ConfigService.ts @@ -79,6 +79,7 @@ const defaultLayerConfig: Partial = { duration: 4, trailLength: 0.15, }, + forward: true, // 默认是正方向 }; // @see https://github.com/epoberezkin/ajv#options diff --git a/packages/core/src/services/layer/ILayerService.ts b/packages/core/src/services/layer/ILayerService.ts index 2f2f00c49c..d418a671a3 100644 --- a/packages/core/src/services/layer/ILayerService.ts +++ b/packages/core/src/services/layer/ILayerService.ts @@ -130,6 +130,7 @@ export interface ILayer { scale(field: string | number | IScaleOptions, cfg?: IScale): ILayer; size(field: StyleAttrField, value?: StyleAttributeOption): ILayer; color(field: StyleAttrField, value?: StyleAttributeOption): ILayer; + texture(field: StyleAttrField, value?: StyleAttributeOption): ILayer; shape(field: StyleAttrField, value?: StyleAttributeOption): ILayer; label(field: StyleAttrField, value?: StyleAttributeOption): ILayer; animate(option: Partial | boolean): ILayer; @@ -244,6 +245,8 @@ export interface ILayerConfig { enableMultiPassRenderer: boolean; passes: Array; + forward: boolean; // 正方向 + /** * 开启拾取 */ @@ -274,6 +277,10 @@ export interface ILayerConfig { */ enableLighting: boolean; animateOption: Partial; + /** + * layer point text 是否是 iconfont 模式 + */ + iconfont: boolean; onHover(pickedFeature: IPickedFeature): void; onClick(pickedFeature: IPickedFeature): void; } diff --git a/packages/core/src/services/scene/ISceneService.ts b/packages/core/src/services/scene/ISceneService.ts index 841c0b9c4c..28b77cf473 100644 --- a/packages/core/src/services/scene/ISceneService.ts +++ b/packages/core/src/services/scene/ISceneService.ts @@ -6,6 +6,8 @@ import { IRenderConfig } from '../renderer/IRendererService'; export interface ISceneService { destroyed: boolean; loaded: boolean; + fontFamily: string; + loadFont: boolean; on(type: string, handle: (...args: any[]) => void): void; off(type: string, handle: (...args: any[]) => void): void; removeAllListeners(event?: string): this; @@ -16,6 +18,7 @@ export interface ISceneService { getSceneContainer(): HTMLDivElement; getMarkerContainer(): HTMLElement; exportPng(type?: 'png' | 'jpg'): string; + addFontFace(fontname: string, fontpath: string): void; destroy(): void; } // scene 事件 diff --git a/packages/core/src/services/scene/SceneService.ts b/packages/core/src/services/scene/SceneService.ts index 75c0fcc246..8e87893db4 100644 --- a/packages/core/src/services/scene/SceneService.ts +++ b/packages/core/src/services/scene/SceneService.ts @@ -35,6 +35,10 @@ export default class Scene extends EventEmitter implements ISceneService { public destroyed: boolean = false; public loaded: boolean = false; + // loadFont 判断用户当前是否添加自定义字体 + public loadFont: boolean = false; + // fontFamily 用户当前自己添加的字体的名称 + public fontFamily: string = ''; @inject(TYPES.SceneID) private readonly id: string; @@ -247,6 +251,11 @@ export default class Scene extends EventEmitter implements ISceneService { if (this.destroyed) { this.destroy(); } + // @ts-ignore + if (this.loadFont && document.fonts) { + // @ts-ignore + await document.fonts.load(`24px ${this.fontFamily}`, 'L7text'); + } // FIXME: 初始化 marker 容器,可以放到 map 初始化方法中? this.logger.info(' render inited'); this.layerService.initLayers(); @@ -263,6 +272,26 @@ export default class Scene extends EventEmitter implements ISceneService { this.rendering = false; } + /** + * 用户自定义添加第三方字体 (用户使用 layer/point/text/iconfont 的前提需要加载第三方字体文件) + * @param fontFamily + * @param fontPath + */ + public addFontFace(fontFamily: string, fontPath: string): void { + this.fontFamily = fontFamily; + const style = document.createElement('style'); + style.type = 'text/css'; + style.innerText = ` + @font-face{ + font-family: '${fontFamily}'; + src: url('${fontPath}') format('woff2'), + url('${fontPath}') format('woff'), + url('${fontPath}') format('truetype'); + }`; + document.getElementsByTagName('head')[0].appendChild(style); + this.loadFont = true; + } + public getSceneContainer(): HTMLDivElement { return this.$container as HTMLDivElement; } diff --git a/packages/core/src/shaders/project.glsl b/packages/core/src/shaders/project.glsl index ae9710b127..fb1dd4252d 100644 --- a/packages/core/src/shaders/project.glsl +++ b/packages/core/src/shaders/project.glsl @@ -39,7 +39,8 @@ float pixelDistance(vec2 from, vec2 to) { return distance(a1, b1); } -vec2 customProject(vec2 lnglat) { +// gaode2.0 +vec2 customProject(vec2 lnglat) { // 经纬度 => 平面坐标 float t = lnglat.x; float e = lnglat.y; float Sm = 180.0 / PI; @@ -51,4 +52,19 @@ vec2 customProject(vec2 lnglat) { e *= Rm; e = log(tan(PI / 4.0 + e / 2.0)); return vec2(t * Tm, e * Tm); +} + +vec2 unProjCustomCoord(vec2 point) { // 平面坐标 => 经纬度 + float Sm = 57.29577951308232; //180 / Math.PI + float Tm = 6378137.0; + float t = point.x; + float e = point.y; + return vec2(t / Tm * Sm, (2.0 * atan(exp(e / Tm)) - PI / 2.0) * Sm); +} + + +float customPixelDistance(vec2 from, vec2 to) { + vec2 a1 = ProjectFlat(from); + vec2 b1 = ProjectFlat(to); + return distance(a1, b1); } \ No newline at end of file diff --git a/packages/core/src/shaders/projection.glsl b/packages/core/src/shaders/projection.glsl index 7fa4a030dd..ab063be7d3 100644 --- a/packages/core/src/shaders/projection.glsl +++ b/packages/core/src/shaders/projection.glsl @@ -75,7 +75,7 @@ vec3 reverse_offset_normal(vec3 vector) { } if (u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.0 - return vector * vec3(1.0, -1.0, 1.0); + return vector; } return vector; } diff --git a/packages/core/src/utils/font_util.ts b/packages/core/src/utils/font_util.ts index 85399ed28b..da3870e8d1 100644 --- a/packages/core/src/utils/font_util.ts +++ b/packages/core/src/utils/font_util.ts @@ -35,7 +35,6 @@ export function buildMapping({ }); const rowHeight = fontHeight + buffer * 2; - return { mapping, xOffset: x, diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index 9b4dae08f3..7e75af7d49 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -375,6 +375,16 @@ export default class BaseLayer extends EventEmitter return this; } + // 为对应的图层传入纹理的编号名称(point/image 在 shape 方法中传入纹理名称的方法并不通用) + public texture( + field: StyleAttributeField, + values?: StyleAttributeOption, + updateOptions?: Partial, + ) { + this.updateStyleAttribute('texture', field, values, updateOptions); + return this; + } + public rotate( field: StyleAttributeField, values?: StyleAttributeOption, @@ -482,7 +492,6 @@ export default class BaseLayer extends EventEmitter ...this.rawConfig, ...rest, }; - if (this.container) { this.updateLayerConfig(this.rawConfig); this.styleNeedUpdate = true; @@ -500,6 +509,7 @@ export default class BaseLayer extends EventEmitter } return this; } + public render(): ILayer { // if ( // this.needPick() && diff --git a/packages/layers/src/core/interface.ts b/packages/layers/src/core/interface.ts index ef6d574a62..1cf2426810 100644 --- a/packages/layers/src/core/interface.ts +++ b/packages/layers/src/core/interface.ts @@ -8,4 +8,7 @@ export interface ILineLayerStyleOptions { lineType?: keyof typeof lineStyleType; dashArray?: [number, number]; segmentNumber: number; + forward?: boolean; + lineTexture?: boolean; + iconStep?: number; } diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index f58e77fea3..483c6953f9 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -83,24 +83,21 @@ export function LineTriangulation(feature: IEncodeFeature) { if (version === 'GAODE2.x') { // 处理高德2.0几何体构建 - let path1 = coordinates as number[][][] | number[][]; + let path1 = coordinates as number[][][] | number[][]; // 计算位置 if (!Array.isArray(path1[0][0])) { path1 = [coordinates] as number[][][]; } - let path2 = originCoordinates as number[][][] | number[][]; + let path2 = originCoordinates as number[][][] | number[][]; // 计算法线 if (!Array.isArray(path2[0][0])) { path2 = [originCoordinates] as number[][][]; } - path1.forEach((item: any) => { - // 处理带洞的多边形 - line.extrude1(item as number[][]); - }); - - path2.forEach((item: any) => { - // 处理带洞的多边形 - line.extrude2(item as number[][]); - }); + for (let i = 0; i < path1.length; i++) { + // 高德2.0在计算线时,需要使用经纬度计算发现,使用 customCoords.lnglatToCoords 计算的数据来计算顶点的位置 + const item1 = path1[i]; + const item2 = path2[i]; + line.extrude_gaode2(item1 as number[][], item2 as number[][]); + } } else { // 处理非高德2.0的几何体构建 let path = coordinates as number[][][] | number[][]; @@ -229,6 +226,7 @@ export function LineArcTriangulation(feature: IEncodeFeature) { coordinates[1][0], coordinates[1][1], ); + if (i !== segNum - 1) { indexArray.push( ...[0, 1, 2, 1, 3, 2].map((v) => { @@ -237,7 +235,6 @@ export function LineArcTriangulation(feature: IEncodeFeature) { ); } } - // console.log('positions', positions) return { vertices: positions, indices: indexArray, diff --git a/packages/layers/src/heatmap/models/heatmap.ts b/packages/layers/src/heatmap/models/heatmap.ts index b549954f26..e456b9428b 100644 --- a/packages/layers/src/heatmap/models/heatmap.ts +++ b/packages/layers/src/heatmap/models/heatmap.ts @@ -257,13 +257,20 @@ export default class HeatMapModel extends BaseModel { const { opacity, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - const invert = mat4.invert( - mat4.create(), - mat4.fromValues( - // @ts-ignore - ...this.cameraService.getViewProjectionMatrixUncentered(), - ), - ) as mat4; + + // const invert = mat4.invert( + // mat4.create(), + // mat4.fromValues( + // // @ts-ignore + // ...this.cameraService.getViewProjectionMatrixUncentered(), + // ), + // ) as mat4; + const invert = mat4.create(); + mat4.invert( + invert, + this.cameraService.getViewProjectionMatrixUncentered() as mat4, + ); + this.colorModel.draw({ uniforms: { u_opacity: opacity || 1.0, diff --git a/packages/layers/src/heatmap/models/hexagon.ts b/packages/layers/src/heatmap/models/hexagon.ts index 5747b65d9d..d193d1f630 100644 --- a/packages/layers/src/heatmap/models/hexagon.ts +++ b/packages/layers/src/heatmap/models/hexagon.ts @@ -66,8 +66,10 @@ export default class HexagonModel extends BaseModel { size: 3, update: (feature: IEncodeFeature, featureIdx: number) => { // const coordinates = (feature.verison==='GAODE2.x'?feature.originoordinates:feature.coordinates) as number[]; - - const coordinates = feature.coordinates as number[]; + const coordinates = (feature.version === 'GAODE2.x' + ? feature.originCoordinates + : feature.coordinates) as number[]; + // const coordinates = feature.coordinates as number[]; // const coordinates = feature.originCoordinates as number[]; return [coordinates[0], coordinates[1], 0]; }, diff --git a/packages/layers/src/heatmap/shaders/hexagon_vert.glsl b/packages/layers/src/heatmap/shaders/hexagon_vert.glsl index 63d5a1b31e..eddce7da40 100644 --- a/packages/layers/src/heatmap/shaders/hexagon_vert.glsl +++ b/packages/layers/src/heatmap/shaders/hexagon_vert.glsl @@ -12,6 +12,8 @@ uniform mat4 u_ModelMatrix; uniform mat4 u_Mvp; varying vec4 v_color; +uniform vec2 u_SceneCenterMKT; + #pragma include "projection" #pragma include "project" #pragma include "picking" @@ -21,14 +23,18 @@ void main() { mat2 rotationMatrix = mat2(cos(u_angle), sin(u_angle), -sin(u_angle), cos(u_angle)); vec2 offset =(vec2(a_Position.xy * u_radius * rotationMatrix * u_coverage)); - // vec2 lnglat = unProjectFlat(a_Pos.xy + offset); - vec2 lnglat = (a_Pos.xy + offset); - vec4 project_pos = project_position(vec4(lnglat, 0, 1.0)); + vec2 lnglat = unProjectFlat(a_Pos.xy + offset); + + // vec4 project_pos = project_position(vec4(lnglat, 0, 1.0)); // gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy, 0., 1.0)); if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x // gl_Position = u_Mvp * (vec4(project_pos.xy, 0., 1.0)); - gl_Position = u_Mvp * (vec4(a_Pos.xy + offset, 0., 1.0)); + // gl_Position = u_Mvp * (vec4(a_Pos.xy + offset, 0., 1.0)); + vec2 customLnglat = customProject(lnglat) - u_SceneCenterMKT; + vec4 project_pos = project_position(vec4(customLnglat, 0, 1.0)); + gl_Position = u_Mvp * vec4(project_pos.xy, 0.0, 1.0); } else { + vec4 project_pos = project_position(vec4(lnglat, 0, 1.0)); gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy, 0., 1.0)); } setPickingColor(a_PickingColor); diff --git a/packages/layers/src/line/models/arc.ts b/packages/layers/src/line/models/arc.ts index 4d694b1681..fbc1d1cb56 100644 --- a/packages/layers/src/line/models/arc.ts +++ b/packages/layers/src/line/models/arc.ts @@ -23,6 +23,7 @@ export default class ArcModel extends BaseModel { opacity, lineType = 'solid', dashArray = [10, 5], + forward = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; if (dashArray.length === 2) { dashArray.push(0, 0); @@ -33,6 +34,7 @@ export default class ArcModel extends BaseModel { u_line_type: lineStyleObj[lineType || 'solid'], u_dash_array: dashArray, u_blur: 0.9, + u_lineDir: forward ? 1 : -1, }; } diff --git a/packages/layers/src/line/models/line.ts b/packages/layers/src/line/models/line.ts index 7fa53c28f7..7a21a84bb3 100644 --- a/packages/layers/src/line/models/line.ts +++ b/packages/layers/src/line/models/line.ts @@ -3,9 +3,11 @@ import { gl, IAnimateOption, IEncodeFeature, + IImage, ILayerConfig, IModel, IModelUniform, + ITexture2D, } from '@antv/l7-core'; import BaseModel from '../../core/BaseModel'; @@ -18,19 +20,32 @@ const lineStyleObj: { [key: string]: number } = { dash: 1.0, }; export default class LineModel extends BaseModel { + protected texture: ITexture2D; public getUninforms(): IModelUniform { const { opacity, lineType = 'solid', dashArray = [10, 5, 0, 0], + lineTexture = false, + iconStep = 100, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; if (dashArray.length === 2) { dashArray.push(0, 0); } + + if (this.rendererService.getDirty()) { + this.texture.bind(); + } + return { u_opacity: opacity || 1.0, u_line_type: lineStyleObj[lineType], u_dash_array: dashArray, + + u_texture: this.texture, // 贴图 + u_line_texture: lineTexture ? 1.0 : 0.0, // 传入线的标识 + u_icon_step: iconStep, + u_textSize: [1024, this.iconService.canvasHeight || 128], }; } public getAnimateUniforms(): IModelUniform { @@ -42,9 +57,33 @@ export default class LineModel extends BaseModel { } public initModels(): IModel[] { + // const { createTexture2D } = this.rendererService; + // this.texture = createTexture2D({ + // height: 0, + // width: 0, + // }); + // let url = 'https://gw-office.alipayobjects.com/bmw-prod/e91c3630-b79e-45a3-a2b9-feee4b4ccd41.svg' + // this.loadImage(url).then((img) => { + // this.texture = createTexture2D({ + // data: img as HTMLImageElement, + // width: (img as HTMLImageElement).width, + // height: (img as HTMLImageElement).height, + // }); + // this.layerService.renderLayers(); + // }) + this.updateTexture(); + this.iconService.on('imageUpdate', this.updateTexture); + return this.buildModels(); } + public clearModels() { + if (this.texture) { + this.texture.destroy(); + } + this.iconService.off('imageUpdate', this.updateTexture); + } + public buildModels(): IModel[] { return [ this.layer.buildLayerModel({ @@ -182,5 +221,68 @@ export default class LineModel extends BaseModel { }, }, }); + + this.styleAttributeService.registerStyleAttribute({ + name: 'uv', + type: AttributeType.Attribute, + descriptor: { + name: 'a_iconMapUV', + buffer: { + // give the WebGL driver a hint that this buffer may change + usage: gl.DYNAMIC_DRAW, + data: [], + type: gl.FLOAT, + }, + size: 2, + update: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const iconMap = this.iconService.getIconMap(); + const { texture } = feature; + const { x, y } = iconMap[texture as string] || { x: 0, y: 0 }; + return [x, y]; + }, + }, + }); } + + private loadImage(url: IImage) { + return new Promise((resolve, reject) => { + if (url instanceof HTMLImageElement) { + resolve(url); + return; + } + const image = new Image(); + image.crossOrigin = 'anonymous'; + image.onload = () => { + resolve(image); + }; + image.onerror = () => { + reject(new Error('Could not load image at ' + url)); + }; + image.src = url instanceof File ? URL.createObjectURL(url) : url; + }); + } + + private updateTexture = () => { + const { createTexture2D } = this.rendererService; + if (this.texture) { + this.texture.update({ + data: this.iconService.getCanvas(), + }); + this.layer.render(); + return; + } + this.texture = createTexture2D({ + data: this.iconService.getCanvas(), + mag: gl.NEAREST, + min: gl.NEAREST, + premultiplyAlpha: false, + width: 1024, + height: this.iconService.canvasHeight || 128, + }); + }; } diff --git a/packages/layers/src/line/shaders/line_arc_vert.glsl b/packages/layers/src/line/shaders/line_arc_vert.glsl index 013c210346..2b6f8a4308 100644 --- a/packages/layers/src/line/shaders/line_arc_vert.glsl +++ b/packages/layers/src/line/shaders/line_arc_vert.glsl @@ -15,6 +15,7 @@ varying vec2 v_normal; varying float v_distance_ratio; uniform float u_line_type: 0.0; uniform vec4 u_dash_array: [10.0, 5., 0, 0]; +uniform float u_lineDir: 1.0; varying vec4 v_dash_array; #pragma include "projection" #pragma include "project" @@ -32,7 +33,14 @@ vec2 midPoint(vec2 source, vec2 target) { float r2 = r / 2.0 / cos(thetaOffset); float theta2 = theta + thetaOffset; vec2 mid = vec2(r2*cos(theta2) + source.x, r2*sin(theta2) + source.y); - return mid; + if(u_lineDir == 1.0) { // 正向 + return mid; + } else { // 逆向 + // (mid + vmin)/2 = (s + t)/2 + vec2 vmid = source + target - mid; + return vmid; + } + // return mid; } float getSegmentRatio(float index) { return smoothstep(0.0, 1.0, index / (segmentNumber - 1.)); @@ -75,6 +83,9 @@ void main() { } if(u_aimate.x == Animate) { v_distance_ratio = segmentIndex / segmentNumber; + if(u_lineDir != 1.0) { + v_distance_ratio = 1.0 - v_distance_ratio; + } } vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0)); vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0)); diff --git a/packages/layers/src/line/shaders/line_frag.glsl b/packages/layers/src/line/shaders/line_frag.glsl index 3d820ca113..dbdd47a11b 100644 --- a/packages/layers/src/line/shaders/line_frag.glsl +++ b/packages/layers/src/line/shaders/line_frag.glsl @@ -1,12 +1,17 @@ #define LineTypeSolid 0.0 #define LineTypeDash 1.0 #define Animate 0.0 +#define LineTexture 1.0 uniform float u_blur : 0.99; uniform float u_line_type: 0.0; uniform float u_opacity : 1.0; varying vec4 v_color; varying vec2 v_normal; +// line texture +uniform float u_line_texture; +uniform sampler2D u_texture; +uniform vec2 u_textSize; // dash uniform float u_dash_offset : 0.0; @@ -15,19 +20,27 @@ varying float v_distance_ratio; varying vec4 v_dash_array; varying float v_side; +varying float v_distance; +varying vec2 v_offset; +varying float v_a; +varying float v_pixelLen; +varying vec2 v_iconMapUV; +varying float v_strokeWidth; #pragma include "picking" uniform float u_time; -uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; +uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; // 控制运动 // [animate, duration, interval, trailLength], void main() { + float animateSpeed = 0.0; // 运动速度 gl_FragColor = v_color; // anti-alias // float blur = 1.0 - smoothstep(u_blur, 1., length(v_normal.xy)); - gl_FragColor.a *= u_opacity; + gl_FragColor.a *= u_opacity; // 全局透明度 if(u_aimate.x == Animate) { - float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y); + animateSpeed = u_time / u_aimate.y; + float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + animateSpeed); alpha = (alpha + u_aimate.w -1.0) / u_aimate.w; alpha = smoothstep(0., 1., alpha); gl_FragColor.a *= alpha; @@ -43,5 +56,28 @@ void main() { // gl_FragColor.a *=(1.0- step(v_dash_array.x, mod(v_distance_ratio, dashLength))); } - gl_FragColor = filterColor(gl_FragColor); + if(u_line_texture == LineTexture) { // while load texture + float u = fract(mod(v_distance, v_pixelLen)/v_pixelLen - animateSpeed); + float v = length(v_offset)/(v_a*2.0); + v = max(smoothstep(0.95, 1.0, v), v); + vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.; + // gl_FragColor = filterColor(gl_FragColor + texture2D(u_texture, vec2(u, v))); + gl_FragColor = filterColor(gl_FragColor + texture2D(u_texture, uv)); + } else { + gl_FragColor = filterColor(gl_FragColor); + } + // gl_FragColor = filterColor(vec4(1.0, 0.0, 0.0, 1.0)); + + // float r = max(smoothstep( 0.95, 1.0, v_strokeWidth/(v_a*2.0)), v_strokeWidth/(v_a*2.0)); + // if(rV < r || rV > 1.0 - r) { + // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + // } + // float v = length(v_offset)/(v_a*2.0); + // if(v > 0.9) { + // gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0); + // } else if(v < 0.1) { + // gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0); + // } + + // gl_FragColor = filterColor(gl_FragColor); } diff --git a/packages/layers/src/line/shaders/line_vert.glsl b/packages/layers/src/line/shaders/line_vert.glsl index 848948b3a0..ebb0552656 100644 --- a/packages/layers/src/line/shaders/line_vert.glsl +++ b/packages/layers/src/line/shaders/line_vert.glsl @@ -8,6 +8,8 @@ attribute vec2 a_Size; attribute vec3 a_Normal; attribute vec3 a_Position; +attribute vec2 a_iconMapUV; + // dash line attribute float a_Total_Distance; attribute float a_Distance; @@ -15,8 +17,9 @@ attribute float a_Distance; uniform mat4 u_ModelMatrix; uniform mat4 u_Mvp; uniform float u_line_type: 0.0; -uniform vec4 u_dash_array: [10.0, 5.,0, 0]; +uniform vec4 u_dash_array: [10.0, 5., 0, 0]; uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; +uniform float u_icon_step: 100; #pragma include "projection" #pragma include "picking" @@ -27,20 +30,41 @@ varying vec2 v_normal; varying float v_distance_ratio; varying float v_side; +varying float v_distance; +varying vec2 v_offset; +varying float v_size; +varying float v_a; +varying float v_pixelLen; +varying vec2 v_iconMapUV; +// varying float v_strokeWidth; void main() { + + v_iconMapUV = a_iconMapUV; + v_distance = a_Distance; + v_pixelLen = project_pixel(u_icon_step); if(u_line_type == LineTypeDash) { v_distance_ratio = a_Distance / a_Total_Distance; + // v_distance_ratio = 0.01; v_dash_array = pow(2.0, 20.0 - u_Zoom) * u_dash_array / a_Total_Distance; } if(u_aimate.x == Animate) { v_distance_ratio = a_Distance / a_Total_Distance; } v_normal = vec2(reverse_offset_normal(a_Normal) * sign(a_Miter)); + + v_color = a_Color; + v_a = project_pixel(a_Size.x); + vec3 size = a_Miter * setPickingSize(a_Size.x) * reverse_offset_normal(a_Normal); + vec2 offset = project_pixel(size.xy); + // v_strokeWidth = project_pixel(2.0); + + v_offset = offset + offset * sign(a_Miter); + v_side = a_Miter * a_Size.x; vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0)); @@ -48,7 +72,7 @@ void main() { if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x // gl_Position = u_Mvp * (vec4(project_pos.xy + offset, a_Size.y, 1.0)); - gl_Position = u_Mvp * (vec4(project_pos.xy + offset, a_Size.y, 1.0)); + gl_Position = u_Mvp * (vec4(project_pos.xy + offset, a_Size.y / 10.0, 1.0)); // 额外除 10.0 是为了和gaode1.x的高度兼容 } else { gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, a_Size.y, 1.0)); } diff --git a/packages/layers/src/plugins/DataMappingPlugin.ts b/packages/layers/src/plugins/DataMappingPlugin.ts index c4adb9b0c9..931443adf7 100644 --- a/packages/layers/src/plugins/DataMappingPlugin.ts +++ b/packages/layers/src/plugins/DataMappingPlugin.ts @@ -1,5 +1,6 @@ import { IEncodeFeature, + IFontService, IGlobalConfigService, ILayer, ILayerPlugin, @@ -26,6 +27,9 @@ export default class DataMappingPlugin implements ILayerPlugin { @inject(TYPES.IMapService) private readonly mapService: IMapService; + @inject(TYPES.IFontService) + private readonly fontService: IFontService; + public apply( layer: ILayer, { @@ -105,6 +109,7 @@ export default class DataMappingPlugin implements ILayerPlugin { data: IParseDataItem[], predata?: IEncodeFeature[], ): IEncodeFeature[] { + // console.log('data', data[0]) const mappedData = data.map((record: IParseDataItem, i) => { const preRecord = predata ? predata[i] : {}; const encodeRecord: IEncodeFeature = { @@ -112,6 +117,7 @@ export default class DataMappingPlugin implements ILayerPlugin { coordinates: record.coordinates, ...preRecord, }; + attributes .filter((attribute) => attribute.scale !== undefined) .forEach((attribute: IStyleAttribute) => { @@ -127,19 +133,21 @@ export default class DataMappingPlugin implements ILayerPlugin { // @ts-ignore encodeRecord[attribute.name] = Array.isArray(values) && values.length === 1 ? values[0] : values; + + // 增加对 layer/text/iconfont unicode 映射的解析 + if (attribute.name === 'shape') { + encodeRecord.shape = this.fontService.getIconFontKey( + encodeRecord[attribute.name] as string, + ); + } }); return encodeRecord; }) as IEncodeFeature[]; + // console.log('mappedData', mappedData[0]) - // console.log('mappedData', unProjectFlat(mappedData[0].coordinates as [number, number])) - // @ts-ignore - // console.log(this.mapService.getCustomCoordCenter()) - // 根据地图的类型判断是否需要对点位数据进行处理 - if (this.mapService.version === 'GAODE2.x') { - // 若是高德2.0则需要对坐标进行相对偏移 - + // 根据地图的类型判断是否需要对点位数据进行处理, 若是高德2.0则需要对坐标进行相对偏移 + if (mappedData.length > 0 && this.mapService.version === 'GAODE2.x') { if (typeof mappedData[0].coordinates[0] === 'number') { - // console.log('111', mappedData) // 单个的点数据 // @ts-ignore mappedData.map((d) => { @@ -151,7 +159,6 @@ export default class DataMappingPlugin implements ILayerPlugin { // d.coordinates = this.mapService.lngLatToCoord(unProjectFlat(d.coordinates)); }); } else { - // console.log('2') // 连续的线、面数据 // @ts-ignore mappedData.map((d) => { diff --git a/packages/layers/src/point/models/image.ts b/packages/layers/src/point/models/image.ts index 2970cb2f24..99d52641b4 100644 --- a/packages/layers/src/point/models/image.ts +++ b/packages/layers/src/point/models/image.ts @@ -108,7 +108,6 @@ export default class ImageModel extends BaseModel { attributeIdx: number, ) => { const iconMap = this.iconService.getIconMap(); - const { shape } = feature; const { x, y } = iconMap[shape as string] || { x: 0, y: 0 }; return [x, y]; diff --git a/packages/layers/src/point/models/text.ts b/packages/layers/src/point/models/text.ts index 6a876d1040..7381813022 100644 --- a/packages/layers/src/point/models/text.ts +++ b/packages/layers/src/point/models/text.ts @@ -292,7 +292,7 @@ export default class TextModel extends BaseModel { return padBounds(bounds, 0.5); } /** - * 生成文字纹理 + * 生成文字纹理(生成文字纹理字典) */ private initTextFont() { const { @@ -315,12 +315,39 @@ export default class TextModel extends BaseModel { characterSet, fontWeight, fontFamily, + iconfont: false, }); } + /** - * 生成文字布局 + * 生成 iconfont 纹理字典 */ - private generateGlyphLayout() { + private initIconFontTex() { + const { + fontWeight = '400', + fontFamily = 'sans-serif', + } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; + const data = this.layer.getEncodedData(); + const characterSet: string[] = []; + data.forEach((item: IEncodeFeature) => { + let { shape = '' } = item; + shape = shape.toString(); + if (characterSet.indexOf(shape) === -1) { + characterSet.push(shape); + } + }); + this.fontService.setFontOptions({ + characterSet, + fontWeight, + fontFamily, + iconfont: true, + }); + } + + /** + * 生成文字布局(对照文字纹理字典提取对应文字的位置很好信息) + */ + private generateGlyphLayout(iconfont: boolean) { // TODO:更新文字布局 const { mapping } = this.fontService; const { @@ -331,6 +358,7 @@ export default class TextModel extends BaseModel { const data = this.layer.getEncodedData(); this.glyphInfo = data.map((feature: IEncodeFeature) => { const { shape = '', id, size = 1 } = feature; + const shaping = shapeText( shape.toString(), mapping, @@ -340,6 +368,7 @@ export default class TextModel extends BaseModel { 'center', spacing, textOffset, + iconfont, ); const glyphQuads = getGlyphQuads(shaping, textOffset, false); feature.shaping = shaping; @@ -347,13 +376,8 @@ export default class TextModel extends BaseModel { // feature.centroid = calculteCentroid(coordinates); feature.centroid = calculteCentroid(feature.coordinates); - // if (feature.version === 'GAODE2.x') { - // // 此时地图为高德2.0 - // feature.originCentroid = calculteCentroid(feature.originCoordinates); - // } else { - // // 此时地图不是高德2.0 originCentroid == centroid - // feature.originCentroid = feature.centroid; - // } + + // 此时地图高德2.0 originCentroid == centroid feature.originCentroid = feature.version === 'GAODE2.x' ? calculteCentroid(feature.originCoordinates) @@ -421,10 +445,13 @@ export default class TextModel extends BaseModel { * 初始化文字布局 */ private initGlyph() { - // 1.生成文字纹理 - this.initTextFont(); + const { iconfont = false } = this.layer.getLayerConfig(); + // 1.生成文字纹理(或是生成 iconfont) + iconfont ? this.initIconFontTex() : this.initTextFont(); + // this.initTextFont(); + // 2.生成文字布局 - this.generateGlyphLayout(); + this.generateGlyphLayout(iconfont); } /** * 更新文字纹理 diff --git a/packages/layers/src/point/shaders/image_frag.glsl b/packages/layers/src/point/shaders/image_frag.glsl index 77a6c90baf..1d3fb410f5 100644 --- a/packages/layers/src/point/shaders/image_frag.glsl +++ b/packages/layers/src/point/shaders/image_frag.glsl @@ -11,13 +11,13 @@ uniform float u_opacity : 1; varying float v_size; #pragma include "picking" void main(){ -vec2 pos= v_uv / u_textSize + gl_PointCoord / u_textSize * 64.; -vec4 textureColor=texture2D(u_texture,pos); -if(all(lessThan(v_color, vec4(1.0+0.00001))) && all(greaterThan(v_color, vec4(1.0-0.00001))) || v_color==vec4(1.0)){ - gl_FragColor= textureColor; -}else { - gl_FragColor= step(0.01, textureColor.z) * v_color; -} -gl_FragColor.a =gl_FragColor.a * u_opacity; -gl_FragColor = filterColor(gl_FragColor); + vec2 pos= v_uv / u_textSize + gl_PointCoord / u_textSize * 64.; + vec4 textureColor=texture2D(u_texture,pos); + if(all(lessThan(v_color, vec4(1.0+0.00001))) && all(greaterThan(v_color, vec4(1.0-0.00001))) || v_color==vec4(1.0)){ + gl_FragColor= textureColor; + }else { + gl_FragColor= step(0.01, textureColor.z) * v_color; + } + gl_FragColor.a =gl_FragColor.a * u_opacity; + gl_FragColor = filterColor(gl_FragColor); } diff --git a/packages/layers/src/raster/raster.ts b/packages/layers/src/raster/raster.ts index 05216ba8c4..6ca2f1af79 100644 --- a/packages/layers/src/raster/raster.ts +++ b/packages/layers/src/raster/raster.ts @@ -29,7 +29,7 @@ interface IRasterLayerStyleOptions { export default class RasterLayer extends BaseLayer { public type: string = 'RasterLayer'; - protected texture: ITexture2D; + protected rasterTexture: ITexture2D; protected colorTexture: ITexture2D; public getAnimateUniforms(): IModelUniform { @@ -39,7 +39,7 @@ export default class RasterLayer extends BaseLayer { public buildModels() { const parserDataItem = this.getSource().data.dataArray[0]; const { createTexture2D } = this.rendererService; - this.texture = createTexture2D({ + this.rasterTexture = createTexture2D({ data: parserDataItem.data, width: parserDataItem.width, height: parserDataItem.height, @@ -65,7 +65,7 @@ export default class RasterLayer extends BaseLayer { model.draw({ uniforms: { u_opacity: opacity || 1, - u_texture: this.texture, + u_texture: this.rasterTexture, u_min: min, u_width: width, u_height: height, diff --git a/packages/layers/src/raster/raster2d.ts b/packages/layers/src/raster/raster2d.ts index f563bb0fc1..1820ba87ba 100644 --- a/packages/layers/src/raster/raster2d.ts +++ b/packages/layers/src/raster/raster2d.ts @@ -13,7 +13,7 @@ interface IRasterLayerStyleOptions { export default class Raster2dLayer extends BaseLayer { public type: string = 'RasterLayer'; - protected texture: ITexture2D; + protected rasterTexture: ITexture2D; protected colorTexture: ITexture2D; public buildModels() { @@ -21,7 +21,7 @@ export default class Raster2dLayer extends BaseLayer { const source = this.getSource(); const { createTexture2D } = this.rendererService; const parserDataItem = this.getSource().data.dataArray[0]; - this.texture = createTexture2D({ + this.rasterTexture = createTexture2D({ data: parserDataItem.data, width: parserDataItem.width, height: parserDataItem.height, @@ -61,12 +61,12 @@ export default class Raster2dLayer extends BaseLayer { const { opacity } = this.getLayerConfig(); const parserDataItem = this.getSource().data.dataArray[0]; const { min, max } = parserDataItem; - if (this.texture) { + if (this.rasterTexture) { this.models.forEach((model) => model.draw({ uniforms: { u_opacity: opacity || 1, - u_texture: this.texture, + u_texture: this.rasterTexture, u_min: min, u_max: max, u_colorTexture: this.colorTexture, diff --git a/packages/layers/src/utils/extrude_polyline.ts b/packages/layers/src/utils/extrude_polyline.ts index 83febd3bc1..591937a295 100644 --- a/packages/layers/src/utils/extrude_polyline.ts +++ b/packages/layers/src/utils/extrude_polyline.ts @@ -87,6 +87,51 @@ export default class ExtrudePolyline { startIndex: 0, }; } + + public extrude_gaode2(points: number[][], originPoints: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1] as vec2; + const originLast = originPoints[i - 1] as vec2; + + const cur = points[i] as vec2; + const originCur = originPoints[i] as vec2; + + const next = i < points.length - 1 ? points[i + 1] : null; + const originNext = + i < originPoints.length - 1 ? originPoints[i + 1] : null; + + const amt = this.segment_gaode2( + complex, + count, + last, + cur, + next as vec2, + originLast, + originCur, + originNext as vec2, + ); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } public extrude(points: number[][]) { const complex = this.complex; if (points.length <= 1) { @@ -115,61 +160,221 @@ export default class ExtrudePolyline { complex.startIndex = complex.positions.length / 6; return complex; } - public extrude1(points: number[][]) { - const complex = this.complex; - if (points.length <= 1) { - return complex; - } - this.lastFlip = -1; - this.started = false; - this.normal = null; - this.totalDistance = 0; - // 去除数组里重复的点 - // points = getArrayUnique(points); - const total = points.length; - let count = complex.startIndex; - for (let i = 1; i < total; i++) { - const last = points[i - 1] as vec2; - const cur = points[i] as vec2; - const next = i < points.length - 1 ? points[i + 1] : null; - const amt = this.segment1(complex, count, last, cur, next as vec2); - count += amt; - } + private segment_gaode2( + complex: any, + index: number, + last: vec2, + cur: vec2, + next: vec2, + originLast: vec2, + originCur: vec2, + originNext: vec2, + ) { + let count = 0; + const indices = complex.indices; + const positions = complex.positions; + const normals = complex.normals; + const capSquare = this.cap === 'square'; + const joinBevel = this.join === 'bevel'; + const flatCur = aProjectFlat([originCur[0], originCur[1]]) as [ + number, + number, + ]; + const flatLast = aProjectFlat([originLast[0], originLast[1]]) as [ + number, + number, + ]; + direction(lineA, cur, last); + let segmentDistance = 0; if (this.dash) { - for (let i = 0; i < complex.positions.length / 6; i++) { - complex.positions[i * 6 + 5] = this.totalDistance; + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + // if the end cap is type square, we can just push the verts out a bit + if (capSquare) { + // vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness); + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.add(out1, this.normal, lineA); + vec2.add(out2, this.normal, lineA); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + positions.push( + last[0], + last[1], + 0, + this.totalDistance - segmentDistance, + -this.thickness, + 0, + ); + positions.push( + last[0], + last[1], + 0, + this.totalDistance - segmentDistance, + this.thickness, + 0, + ); + } else { + this.extrusions( + positions, + normals, + last, + this.normal, + this.thickness, + this.totalDistance - segmentDistance, + ); } } - complex.startIndex = complex.positions.length / 6; - return complex; - } - public extrude2(points: number[][]) { - const complex = this.complex; - if (points.length <= 1) { - return complex; - } - this.lastFlip = -1; - this.started = false; - this.normal = null; - this.totalDistance = 0; - // 去除数组里重复的点 - // points = getArrayUnique(points); - const total = points.length; - let count = complex.startIndex; - for (let i = 1; i < total; i++) { - const last = points[i - 1] as vec2; - const cur = points[i] as vec2; - const next = i < points.length - 1 ? points[i + 1] : null; - const amt = this.segment2(complex, count, last, cur, next as vec2); - count += amt; - } - if (this.dash) { - for (let i = 0; i < complex.positions.length / 6; i++) { - complex.positions[i * 6 + 5] = this.totalDistance; + + indices.push(index + 0, index + 1, index + 2); + + if (!next) { + computeNormal(this.normal, lineA); + if (capSquare) { + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.sub(out2, lineA, this.normal); + vec2.add(out1, lineA, this.normal); + + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness, + 0, + ); + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness, + 0, + ); + } else { + this.extrusions( + positions, + normals, + cur, + this.normal, + this.thickness, + this.totalDistance, + ); } + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + count += 2; + } else { + if (isPointEqual(cur, next)) { + vec2.add( + next, + cur, + vec2.normalize(next, vec2.subtract(next, cur, last)), + ); + } + direction(lineB, next, cur); + // stores tangent & miter + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + // normal(tmp, lineA) + + // get orientation + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + let bevel = joinBevel; + if (!bevel && this.join === 'miter') { + const limit = miterLen; + if (limit > this.miterLimit) { + bevel = true; + } + } + + if (bevel) { + normals.push(this.normal[0], this.normal[1], 0); + normals.push(miter[0], miter[1], 0); + + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + -this.thickness * flip, + 0, + ); + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + this.thickness * flip, + 0, + ); + indices.push( + ...(this.lastFlip !== -flip + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + // now add the bevel triangle + indices.push(index + 2, index + 3, index + 4); + + computeNormal(tmp, lineB); + vec2.copy(this.normal, tmp); // store normal for next round + normals.push(this.normal[0], this.normal[1], 0); + positions.push( + cur[0], + cur[1], + 0, + this.totalDistance, + -this.thickness * flip, + 0, + ); + count += 3; + } else { + this.extrusions( + positions, + normals, + cur, + miter, + miterLen, + this.totalDistance, + ); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + flip = -1; + + // the miter is now the normal for our next join + vec2.copy(this.normal, miter); + count += 2; + } + this.lastFlip = flip; } - complex.startIndex = complex.positions.length / 6; - return complex; + return count; } private segment( complex: any, @@ -385,286 +590,6 @@ export default class ExtrudePolyline { } return count; } - private segment1( - complex: any, - index: number, - last: vec2, - cur: vec2, - next: vec2, - ) { - let count = 0; - const indices = complex.indices; - const positions = complex.positions; - const capSquare = this.cap === 'square'; - const joinBevel = this.join === 'bevel'; - const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; - const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; - direction(lineA, flatCur, flatLast); - let segmentDistance = 0; - if (this.dash) { - segmentDistance = this.lineSegmentDistance(flatCur, flatLast); - this.totalDistance += segmentDistance; - } - - if (!this.normal) { - this.normal = vec2.create(); - computeNormal(this.normal, lineA); - } - if (!this.started) { - this.started = true; - - // if the end cap is type square, we can just push the verts out a bit - if (capSquare) { - // vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness); - const out1 = vec2.create(); - const out2 = vec2.create(); - vec2.add(out1, this.normal, lineA); - vec2.add(out2, this.normal, lineA); - - positions.push( - last[0], - last[1], - 0, - this.totalDistance - segmentDistance, - -this.thickness, - 0, - ); - positions.push( - last[0], - last[1], - 0, - this.totalDistance - segmentDistance, - this.thickness, - 0, - ); - } else { - this.extrusionsPosition( - positions, - last, - this.thickness, - this.totalDistance - segmentDistance, - ); - } - } - - indices.push(index + 0, index + 1, index + 2); - - if (!next) { - computeNormal(this.normal, lineA); - if (capSquare) { - const out1 = vec2.create(); - const out2 = vec2.create(); - vec2.sub(out2, lineA, this.normal); - vec2.add(out1, lineA, this.normal); - - positions.push( - cur[0], - cur[1], - 0, - this.totalDistance, - this.thickness, - 0, - ); - positions.push( - cur[0], - cur[1], - 0, - this.totalDistance, - this.thickness, - 0, - ); - } else { - this.extrusionsPosition( - positions, - cur, - this.thickness, - this.totalDistance, - ); - } - indices.push( - ...(this.lastFlip === 1 - ? [index, index + 2, index + 3] - : [index + 2, index + 1, index + 3]), - ); - count += 2; - } else { - const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; - if (isPointEqual(flatCur, flatNext)) { - vec2.add( - flatNext, - flatCur, - vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), - ); - } - direction(lineB, flatNext, flatCur); - - const [miterLen, miter] = computeMiter( - tangent, - vec2.create(), - lineA, - lineB, - this.thickness, - ); - let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; - let bevel = joinBevel; - if (!bevel && this.join === 'miter') { - const limit = miterLen; - if (limit > this.miterLimit) { - bevel = true; - } - } - if (bevel) { - positions.push( - cur[0], - cur[1], - 0, - this.totalDistance, - -this.thickness * flip, - 0, - ); - positions.push( - cur[0], - cur[1], - 0, - this.totalDistance, - this.thickness * flip, - 0, - ); - indices.push( - ...(this.lastFlip !== -flip - ? [index, index + 2, index + 3] - : [index + 2, index + 1, index + 3]), - ); - indices.push(index + 2, index + 3, index + 4); - - computeNormal(tmp, lineB); - vec2.copy(this.normal, tmp); // store normal for next round - - positions.push( - cur[0], - cur[1], - 0, - this.totalDistance, - -this.thickness * flip, - 0, - ); - count += 3; - } else { - this.extrusionsPosition(positions, cur, miterLen, this.totalDistance); - indices.push( - ...(this.lastFlip === 1 - ? [index, index + 2, index + 3] - : [index + 2, index + 1, index + 3]), - ); - flip = -1; - vec2.copy(this.normal, miter); - count += 2; - } - this.lastFlip = flip; - } - return count; - } - private segment2( - complex: any, - index: number, - last: vec2, - cur: vec2, - next: vec2, - ) { - let count = 0; - const normals = complex.normals; - const capSquare = this.cap === 'square'; - const joinBevel = this.join === 'bevel'; - const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; - const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; - direction(lineA, flatCur, flatLast); - let segmentDistance = 0; - if (this.dash) { - segmentDistance = this.lineSegmentDistance(flatCur, flatLast); - this.totalDistance += segmentDistance; - } - - if (!this.normal) { - this.normal = vec2.create(); - computeNormal(this.normal, lineA); - } - if (!this.started) { - this.started = true; - - if (capSquare) { - const out1 = vec2.create(); - const out2 = vec2.create(); - vec2.add(out1, this.normal, lineA); - vec2.add(out2, this.normal, lineA); - normals.push(out2[0], out2[1], 0); - normals.push(out1[0], out1[1], 0); - } else { - this.extrusionsNormal(normals, this.normal); - } - } - - if (!next) { - computeNormal(this.normal, lineA); - if (capSquare) { - const out1 = vec2.create(); - const out2 = vec2.create(); - vec2.sub(out2, lineA, this.normal); - vec2.add(out1, lineA, this.normal); - normals.push(out2[0], out2[1], 0); - normals.push(out1[0], out1[1], 0); - } else { - this.extrusionsNormal(normals, this.normal); - } - - count += 2; - } else { - const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; - if (isPointEqual(flatCur, flatNext)) { - vec2.add( - flatNext, - flatCur, - vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), - ); - } - direction(lineB, flatNext, flatCur); - - const [miterLen, miter] = computeMiter( - tangent, - vec2.create(), - lineA, - lineB, - this.thickness, - ); - - let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; - let bevel = joinBevel; - if (!bevel && this.join === 'miter') { - const limit = miterLen; - if (limit > this.miterLimit) { - bevel = true; - } - } - - if (bevel) { - normals.push(this.normal[0], this.normal[1], 0); - normals.push(miter[0], miter[1], 0); - - computeNormal(tmp, lineB); - vec2.copy(this.normal, tmp); // store normal for next round - normals.push(this.normal[0], this.normal[1], 0); - - count += 3; - } else { - this.extrusionsNormal(normals, miter); - flip = -1; - vec2.copy(this.normal, miter); - count += 2; - } - this.lastFlip = flip; - } - return count; - } - private extrusions( positions: number[], normals: number[], @@ -678,20 +603,6 @@ export default class ExtrudePolyline { positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0); positions.push(point[0], point[1], 0, distanceRadio, thickness, 0); } - private extrusionsPosition( - positions: number[], - point: vec2, // 顶点 - thickness: number, // 高度 - distanceRadio: number, - ) { - positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0); - positions.push(point[0], point[1], 0, distanceRadio, thickness, 0); - } - private extrusionsNormal(normals: number[], normal: vec2) { - // 法向量 - normals.push(normal[0], normal[1], 0); - normals.push(normal[0], normal[1], 0); - } private lineSegmentDistance(b1: vec2, a1: vec2) { const dx = a1[0] - b1[0]; const dy = a1[1] - b1[1]; diff --git a/packages/layers/src/utils/symbol-layout.ts b/packages/layers/src/utils/symbol-layout.ts index 4c125e6931..79a7b05eaa 100644 --- a/packages/layers/src/utils/symbol-layout.ts +++ b/packages/layers/src/utils/symbol-layout.ts @@ -197,6 +197,81 @@ function shapeLines( shaping.right = shaping.left + maxLineLength; } +function shapeIconFont( + shaping: any, + glyphMap: any, + iconfonts: any[], + lineHeight: number, + textAnchor: anchorType, + textJustify: string, + spacing: number, +) { + // buffer 为 4 + const yOffset = -8; + + let x = 0; + let y = yOffset; + + let maxLineLength = 0; + const positionedGlyphs = shaping.positionedGlyphs; + + const justify = + textJustify === 'right' ? 1 : textJustify === 'left' ? 0 : 0.5; + + const lineStartIndex = positionedGlyphs.length; + iconfonts.forEach((iconfont) => { + const glyph = glyphMap[iconfont]; + const baselineOffset = 0; + + if (glyph) { + positionedGlyphs.push({ + glyph: iconfont, + x, + y: y + baselineOffset, + vertical: false, // TODO:目前只支持水平方向 + scale: 1, + metrics: glyph, + }); + x += glyph.advance + spacing; + } + + // 左右对齐 + if (positionedGlyphs.length !== lineStartIndex) { + const lineLength = x - spacing; + maxLineLength = Math.max(lineLength, maxLineLength); + justifyLine( + positionedGlyphs, + glyphMap, + lineStartIndex, + positionedGlyphs.length - 1, + justify, + ); + } + + x = 0; + y += lineHeight; + }); + + const { horizontalAlign, verticalAlign } = getAnchorAlignment(textAnchor); + align( + positionedGlyphs, + justify, + horizontalAlign, + verticalAlign, + maxLineLength, + lineHeight, + iconfonts.length, + ); + + // 计算包围盒 + const height = y - yOffset; + + shaping.top += -verticalAlign * height; + shaping.bottom = shaping.top + height; + shaping.left += -horizontalAlign * maxLineLength; + shaping.right = shaping.left + maxLineLength; +} + /** * 计算文本中每个独立字符相对锚点的位置 * @@ -207,6 +282,7 @@ function shapeLines( * @param {string} textJustify 左右对齐 * @param {number} spacing 字符间距 * @param {[number, number]} translate 文本水平 & 垂直偏移量 + * @param {[boolean]} isIconFont 是否是 iconfont * @return {boolean|shaping} 每个字符相对于锚点的位置 */ export function shapeText( @@ -217,6 +293,7 @@ export function shapeText( textJustify: string, spacing: number, translate: [number, number] = [0, 0], + isIconFont: boolean, ) { // TODO:处理换行 const lines = text.split('\n'); @@ -231,16 +308,25 @@ export function shapeText( lineCount: lines.length, text, }; - - shapeLines( - shaping, - glyphs, - lines, - lineHeight, - textAnchor, - textJustify, - spacing, - ); + isIconFont + ? shapeIconFont( + shaping, + glyphs, + lines, + lineHeight, + textAnchor, + textJustify, + spacing, + ) + : shapeLines( + shaping, + glyphs, + lines, + lineHeight, + textAnchor, + textJustify, + spacing, + ); if (!positionedGlyphs.length) { return false; } diff --git a/packages/maps/src/amap2/Viewport.ts b/packages/maps/src/amap2/Viewport.ts index 985df243f6..6b19bd7d48 100644 --- a/packages/maps/src/amap2/Viewport.ts +++ b/packages/maps/src/amap2/Viewport.ts @@ -1,7 +1,5 @@ import { IMapCamera, IViewport } from '@antv/l7-core'; import { mat4, vec3 } from 'gl-matrix'; - -const DEGREES_TO_RADIANS = Math.PI / 180; export default class Viewport implements IViewport { private projectionMatrix: mat4 = mat4.create(); private viewMatrix: mat4 = mat4.create(); @@ -22,11 +20,12 @@ export default class Viewport implements IViewport { aspect = 1, near = 0.1, far = 1000, - fov = 0, - - pitch = 0, - bearing = 0, - cameraHeight = 1, + fov = 45, + // @ts-ignore + // left, + // right, + // bottom, + // top, } = mapCamera; this.zoom = zoom; this.center = center; @@ -39,31 +38,23 @@ export default class Viewport implements IViewport { near, far, ); - // mat4.perspective(this.projectionMatrix, 0.91, aspect, near, far); - // const pitchInRadians = pitch * DEGREES_TO_RADIANS; - // const rotationInRadians = (360 - bearing) * DEGREES_TO_RADIANS; + // ortho(out, left, right, bottom, top, near, far) + // mat4.ortho(this.projectionMatrix, left, right, bottom, top, near, far) + // console.log(left, right, bottom, top, near, far) // 计算相机矩阵 viewMatrix - // const eyePoint = vec3.fromValues(...cameraPosition); - const eyePoint = vec3.fromValues( - cameraPosition[0], - cameraPosition[1], - cameraPosition[2], - ); + // console.log(cameraPosition) + const eyePoint = vec3.fromValues(...cameraPosition); + // const eyePoint = vec3.fromValues(cameraPosition[0], cameraPosition[1], 0.1); // 计算相机矩阵 viewMatrix - // const eyePoint = vec3.fromValues( - // (cameraPosition[2]) * Math.sin(pitchInRadians) * Math.sin(rotationInRadians), - // -(cameraPosition[2]) * Math.sin(pitchInRadians) * Math.cos(rotationInRadians), - // (cameraPosition[2]) * Math.cos(pitchInRadians), - // ); + const lookAtPoint = vec3.fromValues(...lookAt); + // const lookAtPoint = vec3.fromValues(...cameraPosition); + // const lookAtPoint = vec3.fromValues(cameraPosition[0], cameraPosition[1], -0.1); // const lookAtPoint = vec3.fromValues(0, 0, 0); + const upDirect = vec3.fromValues(...up); - // const upDirect = vec3.fromValues( - // -Math.cos(pitchInRadians) * Math.sin(rotationInRadians), - // Math.cos(pitchInRadians) * Math.cos(rotationInRadians), - // Math.sin(pitchInRadians), - // ); + // const upDirect = vec3.fromValues(0, 1, 0); mat4.lookAt(this.viewMatrix, eyePoint, lookAtPoint, upDirect); this.viewUncenteredMatrix = mat4.clone(this.viewMatrix); @@ -92,8 +83,8 @@ export default class Viewport implements IViewport { } public getZoomScale(): number { - // 512 尺寸下的缩放:2 ^ 19 - return 524288; + // 512 尺寸下的缩放:2 ^ 20 + return 1048576; } public getCenter(): [number, number] { diff --git a/packages/maps/src/amap2/map.ts b/packages/maps/src/amap2/map.ts index 8d178134ff..ea854169c7 100644 --- a/packages/maps/src/amap2/map.ts +++ b/packages/maps/src/amap2/map.ts @@ -98,7 +98,10 @@ export default class AMapService public setCustomCoordCenter(center: [number, number]) { this.sceneCenter = center; // @ts-ignore - this.sceneCenterMKT = this.map.getProjection().project(...this.sceneCenter); + this.sceneCenterMKT = this.map + // @ts-ignore + .getProjection() + .project(...this.sceneCenter); } public getCustomCoordCenter(): [number, number] { @@ -111,7 +114,6 @@ export default class AMapService // @ts-ignore const proj = this.map.getProjection(); const project = proj.project; - // console.log('proj', proj.project) // 单点 if (!this.sceneCenter) { // @ts-ignore @@ -141,12 +143,16 @@ export default class AMapService } public addMarkerContainer(): void { + if (!this.map) { + return; + } const mapContainer = this.map.getContainer(); if (mapContainer !== null) { - const amap = mapContainer.getElementsByClassName( - 'amap-maps', - )[0] as HTMLElement; - this.markerContainer = DOM.create('div', 'l7-marker-container', amap); + // const amap = mapContainer.getElementsByClassName( + // 'amap-maps', + // )[0] as HTMLElement; + // this.markerContainer = DOM.create('div', 'l7-marker-container2', amap); + this.markerContainer = mapContainer; } } public getMarkerContainer(): HTMLElement { @@ -185,11 +191,10 @@ export default class AMapService } public getType() { - return 'amap'; + return 'amap2'; } public getZoom(): number { - // 统一返回 Mapbox 缩放等级 - return this.map.getZoom() - 1; + return this.map.getZoom(); } public setZoom(zoom: number): void { @@ -251,7 +256,6 @@ export default class AMapService // const NE = amapBound.getNorthEast(); // const SW = amapBound.getSouthWest(); const bounds = this.map.getBounds(); - // console.log('bounds', bounds) // @ts-ignore const NE = bounds.getNorthEast(); @@ -271,11 +275,15 @@ export default class AMapService } public getMinZoom(): number { - const zooms = this.map.get('zooms') as [number, number]; + // const zooms = this.map.get('zooms') as [number, number]; + // @ts-ignore + const zooms = this.map.getZooms() as [number, number]; return zooms[0] - 1; } public getMaxZoom(): number { - const zooms = this.map.get('zooms') as [number, number]; + // const zooms = this.map.get('zooms') as [number, number]; + // @ts-ignore + const zooms = this.map.getZooms() as [number, number]; return zooms[1] - 1; } public setRotation(rotation: number): void { @@ -393,7 +401,6 @@ export default class AMapService ...rest } = this.config; // 高德地图创建独立的container; - // tslint:disable-next-line:typedef await new Promise((resolve) => { const resolveMap = () => { @@ -401,6 +408,18 @@ export default class AMapService this.map = mapInstance as AMap.Map & IAMapInstance; this.$mapContainer = this.map.getContainer(); + // 在使用 map.customCoords 的时候必须使用 + const mapInitCenter = this.map.getCenter(); + // @ts-ignore + this.map.customCoords?.setCenter([ + // @ts-ignore + mapInitCenter.lng, + // @ts-ignore + mapInitCenter.lat, + ]); + // @ts-ignore + this.setCustomCoordCenter([mapInitCenter.lng, mapInitCenter.lat]); + setTimeout(() => { this.map.on('viewchange', this.handleViewChanged); resolve(); @@ -409,7 +428,6 @@ export default class AMapService this.$mapContainer = this.creatAmapContainer( id as string | HTMLDivElement, ); - const map = new AMap.Map(this.$mapContainer, { mapStyle: this.getMapStyle(style as string), zooms: [minZoom, maxZoom], @@ -418,12 +436,10 @@ export default class AMapService }); // @ts-ignore this.map = map; - // 在使用 map.customCoords 的时候必须使用 const mapInitCenter = map.getCenter(); // @ts-ignore map.customCoords.setCenter([mapInitCenter.lng, mapInitCenter.lat]); - // @ts-ignore this.setCustomCoordCenter([mapInitCenter.lng, mapInitCenter.lat]); // 监听地图相机事件 @@ -521,13 +537,16 @@ export default class AMapService // @ts-ignore up, // @ts-ignore - } = this.map.customCoords.getCameraParams(); + // left, right, bottom, top + // @ts-ignore + } = this.map.customCoords?.getCameraParams(); + // // @ts-ignore + // console.log('this.map.customCoords.getCameraParams()', this.map.customCoords.getCameraParams()) + // const { left, right, bottom, top, near, far, position } = this.map.customCoords.getCameraParams(); // @ts-ignore const center = this.map.customCoords.getCenter() as [number, number]; const zoom = this.map.getZoom(); - const pitch = this.map.getPitch(); - const rotation = this.map.getRotation(); // @ts-ignore if (this.cameraChangedCallback) { this.viewport.syncWithMapCamera({ @@ -540,16 +559,12 @@ export default class AMapService up, // AMap 定义的缩放等级 与 Mapbox 相差 1 zoom: zoom - 1, // 与amap1.x对比相差一个级别 - // center: [center.getLng(), center.getLat()], center, offsetOrigin: [position[0], position[1]], - pitch, - bearing: 360 - rotation, + // @ts-ignore + // left, right, bottom, top }); - - // console.log('this.viewport', this.viewport) - // console.log('position', position) // set coordinate system this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20_2); this.cameraChangedCallback(this.viewport); @@ -568,7 +583,6 @@ export default class AMapService * @param e */ private handleViewChanged = (e: any): void => { - // @ts-ignore const { // @ts-ignore fov, @@ -585,11 +599,10 @@ export default class AMapService // @ts-ignore up, // @ts-ignore + // left, right, bottom, top + // @ts-ignore } = this.map.customCoords.getCameraParams(); - const { zoom, pitch, rotation } = e; - // console.log(this.viewport) - // console.log('zoom', zoom, this.map.getZoom()) - // const center = this.map.getCenter(); + const { zoom } = e; // @ts-ignore const center = this.map.customCoords.getCenter() as [number, number]; if (this.cameraChangedCallback) { @@ -604,16 +617,12 @@ export default class AMapService near, // AMap 定义的缩放等级 与 Mapbox 相差 1 zoom: zoom - 1, // 与amap1.x对比相差一个级别 - // center: [center.getLng(), center.getLat()], center, offsetOrigin: [position[0], position[1]], - pitch, - bearing: 360 - rotation, - // // @ts-ignore - // mvp: this.map.customCoords.getMVPMatrix() + // @ts-ignore + // left, right, bottom, top }); - // set coordinate system this.coordinateSystemService.setCoordinateSystem(CoordinateSystem.P20_2); this.cameraChangedCallback(this.viewport); diff --git a/packages/maps/src/amap2/theme.ts b/packages/maps/src/amap2/theme.ts index d7654ddafc..cabb685406 100644 --- a/packages/maps/src/amap2/theme.ts +++ b/packages/maps/src/amap2/theme.ts @@ -1,8 +1,11 @@ export const MapTheme: { [key: string]: any; } = { - dark: 'amap://styles/2a09079c3daac9420ee53b67307a8006?isPublic=true', - light: 'amap://styles/1fd9f8ef9751298f11f5c56968312c70?isPublic=true', + // dark: 'amap://styles/2a09079c3daac9420ee53b67307a8006?isPublic=true', + dark: 'amap://styles/dark', + // light: 'amap://styles/1fd9f8ef9751298f11f5c56968312c70?isPublic=true', + light: 'amap://styles/light', normal: 'amap://styles/normal', - blank: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true', + // blank: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true', + blank: 'amap://styles/1a91e7ec761981d85b35f3099ff781a3', }; diff --git a/packages/maps/src/index.ts b/packages/maps/src/index.ts index c3e1da15fc..00def5f58f 100644 --- a/packages/maps/src/index.ts +++ b/packages/maps/src/index.ts @@ -1,6 +1,7 @@ -import GaodeMap from './amap/'; -import GaodeMap2 from './amap2/'; +// import GaodeMap from './amap/'; +import GaodeMapV1 from './amap/'; +import GaodeMap from './amap2/'; import Map from './map/'; import Mapbox from './mapbox/'; -export { GaodeMap, GaodeMap2, Mapbox, Map }; +export { GaodeMap, GaodeMapV1, Mapbox, Map }; diff --git a/packages/maps/src/mapbox/map.ts b/packages/maps/src/mapbox/map.ts index 01d96e39c2..c2801b6a26 100644 --- a/packages/maps/src/mapbox/map.ts +++ b/packages/maps/src/mapbox/map.ts @@ -40,7 +40,7 @@ import { MapTheme } from './theme'; let mapdivCount = 0; const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12; const MAPBOX_API_KEY = - 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ'; + 'pk.eyJ1IjoibHp4dWUiLCJhIjoiY2tvaWZuM2s4MWZuYjJ1dHI5ZGduYTlrdiJ9.DQCfMRbZzx0VSwecQ69McA'; /** * AMapService */ diff --git a/packages/maps/typings/index.d.ts b/packages/maps/typings/index.d.ts index a74363a13e..6e4f46ffd4 100644 --- a/packages/maps/typings/index.d.ts +++ b/packages/maps/typings/index.d.ts @@ -25,6 +25,7 @@ interface CustomCoords { } interface IAMapInstance { get(key: string): unknown; + getZooms?(): number[]; customCoords?: CustomCoords; } diff --git a/packages/scene/src/index.ts b/packages/scene/src/index.ts index bfd00a0836..6b5046edf8 100644 --- a/packages/scene/src/index.ts +++ b/packages/scene/src/index.ts @@ -187,6 +187,29 @@ class Scene } // asset method + /** + * 为 layer/point/text 支持 iconfont 模式支持 + * @param fontUnicode + * @param name + */ + public addIconFont(name: string, fontUnicode: string): void { + this.fontService.addIconFont(name, fontUnicode); + } + + public addIconFonts(options: string[][]): void { + options.forEach(([name, fontUnicode]) => { + this.fontService.addIconFont(name, fontUnicode); + }); + } + /** + * 用户自定义添加第三方字体 + * @param fontFamily + * @param fontPath + */ + public addFontFace(fontFamily: string, fontPath: string): void { + this.sceneService.addFontFace(fontFamily, fontPath); + } + public addImage(id: string, img: IImage) { this.iconService.addImage(id, img); } diff --git a/stories/Components/components/Popup.tsx b/stories/Components/components/Popup.tsx index b5d92d2975..0266cca851 100644 --- a/stories/Components/components/Popup.tsx +++ b/stories/Components/components/Popup.tsx @@ -1,6 +1,6 @@ // @ts-ignore import { PolygonLayer, Popup, Scene } from '@antv/l7'; -import { Mapbox } from '@antv/l7-maps'; +import { Mapbox, GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class PopupComponent extends React.Component { @@ -17,7 +17,7 @@ export default class PopupComponent extends React.Component { const data = await response.json(); const scene = new Scene({ id: 'map', - map: new Mapbox({ + map: new GaodeMap({ style: 'mapbox://styles/mapbox/streets-v9', center: [110.19382669582967, 30.258134], pitch: 0, diff --git a/stories/Layers/components/RasterLayer.tsx b/stories/Layers/components/RasterLayer.tsx index 78ffa3e09e..4def75e13e 100644 --- a/stories/Layers/components/RasterLayer.tsx +++ b/stories/Layers/components/RasterLayer.tsx @@ -1,3 +1,4 @@ +// @ts-ignore import { RasterLayer, Scene } from '@antv/l7'; import { Mapbox } from '@antv/l7-maps'; import * as dat from 'dat.gui'; diff --git a/stories/Map/components/amap2demo.tsx b/stories/Map/components/amap2demo.tsx index 956f40d5d1..ba5249d172 100644 --- a/stories/Map/components/amap2demo.tsx +++ b/stories/Map/components/amap2demo.tsx @@ -1,5 +1,6 @@ -import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +//@ts-ignore +import { PointLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo extends React.Component { // @ts-ignore @@ -12,7 +13,7 @@ export default class Amap2demo extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ center: [121.107846, 30.267069], pitch: 0, style: 'normal', diff --git a/stories/Map/components/amap2demo_arcLine.tsx b/stories/Map/components/amap2demo_arcLine.tsx index 412464cbde..b47ca96905 100644 --- a/stories/Map/components/amap2demo_arcLine.tsx +++ b/stories/Map/components/amap2demo_arcLine.tsx @@ -1,11 +1,8 @@ -import { vec2, vec3 } from 'gl-matrix'; // @ts-ignore -import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap, Mapbox } from '@antv/l7-maps'; import * as React from 'react'; -import { mat4 } from 'gl-matrix'; - export default class Amap2demo_arcLine extends React.Component { // @ts-ignore private scene: Scene; @@ -17,17 +14,16 @@ export default class Amap2demo_arcLine extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ - pitch: 0, + map: new GaodeMap({ + pitch: 40, center: [107.77791556935472, 35.443286920228644], zoom: 2.9142882493605033, + viewMode: '3D', }), }); this.scene = scene; scene.on('loaded', () => { - console.log('event test'); - fetch( 'https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', ) @@ -50,6 +46,7 @@ export default class Amap2demo_arcLine extends React.Component { opacity: 0.8, blur: 0.99, }); + // .forward(false) scene.addLayer(layer); }); }); diff --git a/stories/Map/components/amap2demo_arcLine3d.tsx b/stories/Map/components/amap2demo_arcLine3d.tsx index 4f15acda75..3990ef6901 100644 --- a/stories/Map/components/amap2demo_arcLine3d.tsx +++ b/stories/Map/components/amap2demo_arcLine3d.tsx @@ -1,5 +1,6 @@ -import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { PointLayer, LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_arcLine3d extends React.Component { @@ -13,10 +14,11 @@ export default class Amap2demo_arcLine3d extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 40, center: [3.438, 40.16797], zoom: 0, + viewMode: '3D', }), }); this.scene = scene; diff --git a/stories/Map/components/amap2demo_arcLineDir.tsx b/stories/Map/components/amap2demo_arcLineDir.tsx new file mode 100644 index 0000000000..5e4ddc59a7 --- /dev/null +++ b/stories/Map/components/amap2demo_arcLineDir.tsx @@ -0,0 +1,174 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_arcLineDir extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + // [116.478935,39.997761], + // [116.478939,39.997825], + // [116.478912,39.998549], + // [116.478912,39.998549], + // [116.478998,39.998555], + // [116.478998,39.998555], + // [116.479282,39.99856], + // [116.479658,39.998528], + // [116.480151,39.998453], + // [116.480784,39.998302], + // [116.480784,39.998302], + // [116.481149,39.998184], + // [116.481573,39.997997], + // [116.481863,39.997846], + // [116.482072,39.997718], + // [116.482362,39.997718], + // [116.483633,39.998935], + // [116.48367,39.998968], + // [116.484648,39.999861] + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 40, + center: [107.77791556935472, 35.443286920228644], + zoom: 2.9142882493605033, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + let data = [ + { + lng1: 91.111891, + lat1: 40.662557, + lng2: 120.342625, + lat2: 37.373799, + }, + { + lng1: 116.98242187499999, + lat1: 43.004647127794435, + lng2: 105.64453124999999, + lat2: 28.998531814051795, + }, + { + lng1: 75.76171875, + lat1: 36.31512514748051, + lng2: 46.23046874999999, + lat2: 52.802761415419674, + }, + ]; + let data2 = [ + { + lng1: 88.59374999999999, + lat1: 52.53627304145948, + lng2: 119.794921875, + lat2: 46.07323062540835, + }, + // { + // lng2: 88.59374999999999, + // lat2: 52.53627304145948, + // lng1: 119.794921875, + // lat1: 46.07323062540835 + // } + ]; + + const layer = new LineLayer({ + blend: 'normal', + }) + .source(data, { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(10) + .shape('arc') + .color('#8C1EB2') + .style({ + forward: false, + }); + scene.addLayer(layer); + + const layer2 = new LineLayer({ blend: 'normal' }) + .source(data, { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(10) + .shape('arc') + .color('#8C1EB2'); + scene.addLayer(layer2); + + const layer3 = new LineLayer({ blend: 'normal' }) + .source(data2, { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(10) + .shape('arc') + .color('#8C1EB2') + .animate(true); + scene.addLayer(layer3); + + const layer4 = new LineLayer({ blend: 'normal' }) + .source(data2, { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(10) + .shape('arc') + .color('#8C1EB2') + .style({ + forward: false, + }) + .animate({ + duration: 4, + interval: 0.3, + trailLength: 0.5, + }); + scene.addLayer(layer4); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_arcLine_greatCircle.tsx b/stories/Map/components/amap2demo_arcLine_greatCircle.tsx index 5a3fdb0eff..f3f246cde2 100644 --- a/stories/Map/components/amap2demo_arcLine_greatCircle.tsx +++ b/stories/Map/components/amap2demo_arcLine_greatCircle.tsx @@ -1,5 +1,6 @@ -import { ILngLat, PointLayer, LineLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_arcLine_greatCircle extends React.Component { @@ -13,10 +14,11 @@ export default class Amap2demo_arcLine_greatCircle extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, center: [107.77791556935472, 35.443286920228644], zoom: 2.9142882493605033, + viewMode: '3D', }), }); this.scene = scene; diff --git a/stories/Map/components/amap2demo_citybuilding.tsx b/stories/Map/components/amap2demo_citybuilding.tsx index 6ee3c91329..0c56efc678 100644 --- a/stories/Map/components/amap2demo_citybuilding.tsx +++ b/stories/Map/components/amap2demo_citybuilding.tsx @@ -1,5 +1,6 @@ -import { PointLayer, CityBuildingLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { CityBuildingLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_citybuilding extends React.Component { @@ -16,11 +17,12 @@ export default class Amap2demo_citybuilding extends React.Component { ); const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ style: 'dark', center: [121.507674, 31.223043], pitch: 65.59312320916906, zoom: 15.4, + viewMode: '3D', }), }); const pointLayer = new CityBuildingLayer(); diff --git a/stories/Map/components/amap2demo_drawControl.tsx b/stories/Map/components/amap2demo_drawControl.tsx new file mode 100644 index 0000000000..9b94c8ab74 --- /dev/null +++ b/stories/Map/components/amap2demo_drawControl.tsx @@ -0,0 +1,63 @@ +//@ts-ignore +import { PointLayer, Scene } from '@antv/l7'; +import { GaodeMapV1 } from '@antv/l7-maps'; +import { DrawControl } from '@antv/l7-draw'; +import * as React from 'react'; +export default class Amap2demo_drawControl extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMapV1({ + pitch: 0, + style: 'light', + layers: [], + center: [116.1608, 40.1119], + zoom: 15, + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + // const layer1 = new AMap.TileLayer.Satellite(); + // scene.map.setLayers([]); + // layer1.setMap(scene.map); + const drawControl = new DrawControl(scene, { + // position: 'topright', + layout: 'horizontal', // horizontal vertical + controls: { + point: true, + polygon: true, + line: true, + circle: true, + rect: true, + delete: true, + }, + }); + scene.addControl(drawControl); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_drilldown.tsx b/stories/Map/components/amap2demo_drilldown.tsx new file mode 100644 index 0000000000..aef75dbd89 --- /dev/null +++ b/stories/Map/components/amap2demo_drilldown.tsx @@ -0,0 +1,69 @@ +// @ts-ignore +import { Scene } from '@antv/l7'; +import { DrillDownLayer } from '@antv/l7-district'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +const colors = ['#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70']; + +export default class Amap2demo_drilldown extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [116.2825, 39.9], + pitch: 0, + style: 'blank', + zoom: 3, + minZoom: 3, + maxZoom: 10, + // viewMode: "3D" + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + new DrillDownLayer(scene, { + data: [], + viewStart: 'Country', + viewEnd: 'City', + fill: { + color: { + field: 'NAME_CHN', + values: colors, + }, + }, + popup: { + enable: true, + Html: (props: any) => { + return `${props.NAME_CHN}`; + }, + }, + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_extrude.tsx b/stories/Map/components/amap2demo_extrude.tsx index 5e81f39a66..dc85fbb830 100644 --- a/stories/Map/components/amap2demo_extrude.tsx +++ b/stories/Map/components/amap2demo_extrude.tsx @@ -1,6 +1,6 @@ // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amapdemo_extrude extends React.Component { @@ -14,12 +14,13 @@ export default class Amapdemo_extrude extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ center: [121.107846, 30.267069], pitch: 35.210526315789465, style: 'normal', zoom: 8, animateEnable: false, + viewMode: '3D', }), }); diff --git a/stories/Map/components/amap2demo_heatmap.tsx b/stories/Map/components/amap2demo_heatmap.tsx index 68c88ae3ba..38496e35ff 100644 --- a/stories/Map/components/amap2demo_heatmap.tsx +++ b/stories/Map/components/amap2demo_heatmap.tsx @@ -1,11 +1,6 @@ -import { - ILngLat, - PointLayer, - PolygonLayer, - Scene, - HeatmapLayer, -} from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { Scene, HeatmapLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_heatmap extends React.Component { @@ -19,7 +14,7 @@ export default class Amap2demo_heatmap extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, center: [127.5671666579043, 7.445038892195569], zoom: 2.632456779444394, diff --git a/stories/Map/components/amap2demo_heatmap3D.tsx b/stories/Map/components/amap2demo_heatmap3D.tsx index 17c38018f7..714b81932e 100644 --- a/stories/Map/components/amap2demo_heatmap3D.tsx +++ b/stories/Map/components/amap2demo_heatmap3D.tsx @@ -1,11 +1,6 @@ -import { - ILngLat, - PointLayer, - PolygonLayer, - Scene, - HeatmapLayer, -} from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { Scene, HeatmapLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_heatmap extends React.Component { @@ -19,12 +14,13 @@ export default class Amap2demo_heatmap extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ // pitch: 58.5, pitch: 0, center: [111.8759, 30.6942], rotation: 0.519, zoom: 3.6116, + viewMode: '3D', }), }); this.scene = scene; diff --git a/stories/Map/components/amap2demo_heatmap_grid.tsx b/stories/Map/components/amap2demo_heatmap_grid.tsx index 637e2f8474..9b233796e7 100644 --- a/stories/Map/components/amap2demo_heatmap_grid.tsx +++ b/stories/Map/components/amap2demo_heatmap_grid.tsx @@ -1,11 +1,6 @@ -import { - ILngLat, - PointLayer, - PolygonLayer, - Scene, - HeatmapLayer, -} from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { Scene, HeatmapLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_heatmap_grid extends React.Component { @@ -19,7 +14,7 @@ export default class Amap2demo_heatmap_grid extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, center: [110.097892, 33.853662], zoom: 4.056, diff --git a/stories/Map/components/amap2demo_heatmap_hexagon.tsx b/stories/Map/components/amap2demo_heatmap_hexagon.tsx index 8aeddbfca7..2f51d3b23b 100644 --- a/stories/Map/components/amap2demo_heatmap_hexagon.tsx +++ b/stories/Map/components/amap2demo_heatmap_hexagon.tsx @@ -1,11 +1,6 @@ -import { - ILngLat, - PointLayer, - PolygonLayer, - Scene, - HeatmapLayer, -} from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { Scene, HeatmapLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_heatmap_hexagon extends React.Component { @@ -19,11 +14,12 @@ export default class Amap2demo_heatmap_hexagon extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ // pitch: 58.5, pitch: 43, center: [120.13383079335335, 29.651873105004427], zoom: 7.068989519212174, + viewMode: '3D', }), }); this.scene = scene; diff --git a/stories/Map/components/amap2demo_heatmap_hexagon_world.tsx b/stories/Map/components/amap2demo_heatmap_hexagon_world.tsx new file mode 100644 index 0000000000..683a07cfca --- /dev/null +++ b/stories/Map/components/amap2demo_heatmap_hexagon_world.tsx @@ -0,0 +1,74 @@ +// @ts-ignore +import { Scene, HeatmapLayer } from '@antv/l7'; +import { GaodeMap, Mapbox } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_heatmap_hexagon_world extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + // pitch: 58.5, + pitch: 43, + center: [120.13383079335335, 29.651873105004427], + zoom: 7.068989519212174, + viewMode: '3D', + style: 'blank', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/3dadb1f5-8f54-4449-8206-72db6e142c40.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new HeatmapLayer({ + autoFit: true, + }) + .source(data, { + transforms: [ + { + type: 'hexagon', + size: 5 * 100000, + }, + ], + }) + .shape('circle') + .active(false) + .color('#aaa') + .style({ + coverage: 0.7, + angle: 0, + opacity: 1.0, + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_iconfont.tsx b/stories/Map/components/amap2demo_iconfont.tsx new file mode 100644 index 0000000000..cfc52d23e2 --- /dev/null +++ b/stories/Map/components/amap2demo_iconfont.tsx @@ -0,0 +1,259 @@ +// @ts-ignore +import { PointLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; +export default class Amap2demo_iconfont extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + let fontFamily = 'iconfont'; + let fontPath = + '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076'; + + + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [121, 30.5], + pitch: 0, + style: 'normal', + zoom: 9, + zooms: [8, 10], + viewMode: '2D' + }), + }); + this.scene = scene; + + scene.addIconFonts([ + ['smallRain', ''], + ['middleRain', ''], + ['hugeRain', ''], + ['sun', ''], + ['cloud', ''], + ]); + + scene.addFontFace(fontFamily, fontPath); + scene.on('loaded', () => { + let originData = [ + { + lng: 120, + lat: 30, + iconType: 'sun', + iconColor: "#FFA500", + backgoundColor: "#00BFFF", + temperature: '28℃', + weather: '晴朗' + }, + { + lng: 120.2, + lat: 30.5, + iconType: 'sun', + iconColor: "#FFA500", + backgoundColor: "#00BFFF", + temperature: '28℃', + weather: '晴朗' + }, + { + lng: 121.5, + lat: 31.4, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120, + lat: 31, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120.6, + lat: 30.8, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 120.5, + lat: 31.3, + iconType: 'cloud', + iconColor: "#F0F8FF", + backgoundColor: "#1E90FF", + temperature: '22℃', + weather: '多云' + }, + { + lng: 121.3, + lat: 30.2, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 121, + lat: 30.5, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 120.6, + lat: 30, + iconType: 'middleRain', + iconColor: "#6495ED", + backgoundColor: "#326EA0", + temperature: '24℃', + weather: '中雨' + }, + { + lng: 120.2, + lat: 29.7, + iconType: 'smallRain', + iconColor: "#6EA0FF", + backgoundColor: "#4678AA", + temperature: '22℃', + weather: '小雨' + }, + { + lng: 121.7, + lat: 29.8, + iconType: 'middleRain', + iconColor: "#6495ED", + backgoundColor: "#326EA0", + temperature: '24℃', + weather: '中雨' + }, + { + lng: 121.5, + lat: 30, + iconType: 'hugeRain', + iconColor: "#4678D2", + backgoundColor: "#285A8C", + temperature: '20℃', + weather: '大雨' + }, + ]; + + const layer = new PointLayer() + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('circle') + .color('backgoundColor') + .size(40) + scene.addLayer(layer); + + + const pointIconFontLayer = new PointLayer({}) + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + } + }, + ) + .shape('iconType', 'text') + .size(30) + .color('iconColor') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [38, 10], // 文本相对锚点的偏移量 [水平, 垂直] + fontFamily, + iconfont: true, + textAllowOverlap: true, + }); + scene.addLayer(pointIconFontLayer); + + const textLayer = new PointLayer({}) + .source(originData, + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .shape('temperature', 'text') + .size(10) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [5, -55], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: "Times New Roman", + textAllowOverlap: true, + }); + scene.addLayer(textLayer); + + const textLayer2 = new PointLayer({}) + .source(originData, + { + parser: { + type: 'json', + x: 'lng', + y: 'lat' + }, + }, + ) + .shape('weather', 'text') + .size(14) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [5, -15], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: "Times New Roman", + textAllowOverlap: true, + }); + scene.addLayer(textLayer2); + + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_image.tsx b/stories/Map/components/amap2demo_image.tsx index f89d4402d4..0ab4624e0f 100644 --- a/stories/Map/components/amap2demo_image.tsx +++ b/stories/Map/components/amap2demo_image.tsx @@ -1,11 +1,8 @@ -import { vec2, vec3 } from 'gl-matrix'; // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; -import { mat4 } from 'gl-matrix'; - export default class Amap2demo_image extends React.Component { // @ts-ignore private scene: Scene; @@ -17,26 +14,27 @@ export default class Amap2demo_image extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, style: 'light', center: [121.434765, 31.256735], zoom: 14.83, + viewMode: '3D', }), }); this.scene = scene; scene.on('loaded', () => { - console.log('event test'); - fetch( 'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json', ) .then((res) => res.json()) .then((data) => { + // console.log('data', data) scene.addImage( '00', 'https://gw.alipayobjects.com/zos/basement_prod/604b5e7f-309e-40db-b95b-4fac746c5153.svg', + // "https://gw-office.alipayobjects.com/bmw-prod/ae2a8580-da3d-43ff-add4-ae9c1bfc75bb.svg" ); scene.addImage( '01', @@ -55,6 +53,7 @@ export default class Amap2demo_image extends React.Component { }, }) .shape('name', ['00', '01', '02']) + // .color("rgba(255, 0, 0, 0.1)") .size(20); scene.addLayer(imageLayer); }); diff --git a/stories/Map/components/amap2demo_imagelayer.tsx b/stories/Map/components/amap2demo_imagelayer.tsx index a608db490c..c52c1cd68d 100644 --- a/stories/Map/components/amap2demo_imagelayer.tsx +++ b/stories/Map/components/amap2demo_imagelayer.tsx @@ -1,5 +1,6 @@ +// @ts-ignore import { ImageLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2, Mapbox } from '@antv/l7-maps'; +import { GaodeMap, Mapbox } from '@antv/l7-maps'; import * as React from 'react'; export default class Amap2demo_imageLayer extends React.Component { @@ -13,11 +14,12 @@ export default class Amap2demo_imageLayer extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ center: [121.268, 30.3628], pitch: 0, style: 'normal', zoom: 10, + viewMode: '3D', }), }); this.scene = scene; diff --git a/stories/Map/components/amap2demo_instance.tsx b/stories/Map/components/amap2demo_instance.tsx new file mode 100644 index 0000000000..787244aba6 --- /dev/null +++ b/stories/Map/components/amap2demo_instance.tsx @@ -0,0 +1,102 @@ +//@ts-ignore +import { PointLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import AMapLoader from '@amap/amap-jsapi-loader'; +import * as React from 'react'; +export default class Amap2demo_instance extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + // const AMAP_API_KEY: string = '15cd8a57710d40c9b7c0e3cc120f1200'; + // const AMAP_VERSION: string = '1.4.15'; + const AMAP_API_KEY: string = 'ff533602d57df6f8ab3b0fea226ae52f'; + const AMAP_VERSION: string = '2.0'; + + AMapLoader.load({ + key: AMAP_API_KEY, // 申请好的Web端开发者Key,首次调用 load 时必填 + version: AMAP_VERSION, // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 + // plugins: plugin, // 需要使用的的插件列表,如比例尺'AMap.Scale'等 + }).then((AMap) => { + const map = new AMap.Map('map', { + viewMode: '3D', + pitch: 0, + mapStyle: 'amap://styles/darkblue', + center: [121.435159, 31.256971], + zoom: 14.89, + minZoom: 10, + }); + + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + mapInstance: map, + }), + }); + + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer() + .source(data, { + parser: { + type: 'json', + x: 'longitude', + y: 'latitude', + }, + }) + .shape('name', [ + 'circle', + 'triangle', + 'square', + 'pentagon', + 'hexagon', + 'octogon', + 'hexagram', + 'rhombus', + 'vesica', + ]) + .size('unit_price', [10, 25]) + .color('name', [ + '#5B8FF9', + '#5CCEA1', + '#5D7092', + '#F6BD16', + '#E86452', + ]) + .style({ + opacity: 0.3, + strokeWidth: 2, + }); + scene.addLayer(pointLayer); + }); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_lineDash.tsx b/stories/Map/components/amap2demo_lineDash.tsx new file mode 100644 index 0000000000..ad7ee62da1 --- /dev/null +++ b/stories/Map/components/amap2demo_lineDash.tsx @@ -0,0 +1,64 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_lineDash extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [116.3956, 39.9392], + pitch: 0, + zoom: 10, + rotation: 0, + style: 'amap://styles/wine', + viewMode: '2D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/0d2f0113-f48b-4db9-8adc-a3937243d5a3.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new LineLayer({}) + .source(data) + .size(1.5) + .shape('line') + .color('标准名称', ['#5B8FF9', '#5CCEA1', '#F6BD16']) + .style({ + lineType: 'dash', + dashArray: [5, 5], + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_lineHeight.tsx b/stories/Map/components/amap2demo_lineHeight.tsx new file mode 100644 index 0000000000..e9af5195a8 --- /dev/null +++ b/stories/Map/components/amap2demo_lineHeight.tsx @@ -0,0 +1,78 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_lineHeight extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 40, + style: 'light', + center: [102.600579, 23.114887], + zoom: 14.66, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/ZVfOvhVCzwBkISNsuKCc.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new LineLayer({}) + .source(data) + .size('ELEV', (h) => { + return [h % 50 === 0 ? 1.0 : 0.5, (h - 1500) * 2]; + }) + .shape('line') + .scale('ELEV', { + type: 'quantize', + }) + .color( + 'ELEV', + [ + '#E4682F', + '#FF8752', + '#FFA783', + '#FFBEA8', + '#FFDCD6', + '#EEF3FF', + '#C8D7F5', + '#A5C1FC', + '#7FA7F9', + '#5F8AE5', + ].reverse(), + ); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_lineStreet.tsx b/stories/Map/components/amap2demo_lineStreet.tsx new file mode 100644 index 0000000000..ff0f493939 --- /dev/null +++ b/stories/Map/components/amap2demo_lineStreet.tsx @@ -0,0 +1,82 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_lineStreet extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.19382669582967, 30.258134], + pitch: 0, + zoom: 16, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', + ) + .then((res) => res.json()) + .then((data) => { + scene.addImage( + '00', + 'https://gw.alipayobjects.com/zos/basement_prod/604b5e7f-309e-40db-b95b-4fac746c5153.svg', + ); + scene.addImage( + '01', + 'https://gw.alipayobjects.com/zos/basement_prod/30580bc9-506f-4438-8c1a-744e082054ec.svg', + ); + scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + ); + + const layer = new LineLayer({}) + .source(data) + .size(5) + .shape('line') + .texture('02') + .color('#25d8b7') + .animate({ + interval: 1, // 间隔 + duration: 1, // 持续时间,延时 + trailLength: 2, // 流线长度 + }) + .style({ + // opacity: 0.5, + lineTexture: true, // 开启线的贴图功能 + iconStep: 50, // 设置贴图纹理的间距 + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_markerlayer.tsx b/stories/Map/components/amap2demo_markerlayer.tsx new file mode 100644 index 0000000000..efac07e85b --- /dev/null +++ b/stories/Map/components/amap2demo_markerlayer.tsx @@ -0,0 +1,81 @@ +//@ts-ignore +import { MarkerLayer, Marker, Scene } from '@antv/l7'; +import { GaodeMap, GaodeMapV1 } from '@antv/l7-maps'; +import * as React from 'react'; +export default class Amap2demo_markerlayer extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + function getColor(v: number) { + return v > 50 + ? '#800026' + : v > 40 + ? '#BD0026' + : v > 30 + ? '#E31A1C' + : v > 20 + ? '#FC4E2A' + : v > 10 + ? '#FD8D3C' + : v > 5 + ? '#FEB24C' + : v > 0 + ? '#FED976' + : '#FFEDA0'; + } + const response = await fetch( + 'https://gw.alipayobjects.com/os/basement_prod/67f47049-8787-45fc-acfe-e19924afe032.json', + ); + const nodes = await response.json(); + const markerLayer = new MarkerLayer(); + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 3, + }), + }); + + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].g !== '1' || nodes[i].v === '') { + continue; + } + const el = document.createElement('label'); + el.className = 'labelclass'; + el.textContent = nodes[i].v + '℃'; + el.style.background = getColor(nodes[i].v); + el.style.borderColor = getColor(nodes[i].v); + const marker = new Marker({ + element: el, + }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); + markerLayer.addMarker(marker); + } + scene.addMarkerLayer(markerLayer); + + this.scene = scene; + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_mesh.tsx b/stories/Map/components/amap2demo_mesh.tsx new file mode 100644 index 0000000000..045dd90d73 --- /dev/null +++ b/stories/Map/components/amap2demo_mesh.tsx @@ -0,0 +1,165 @@ +//@ts-ignore +import { PointLayer, Scene, PolygonLayer, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; +export default class Amap2demo_mesh extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'dark', + pitch: 40, + center: [118.8, 32.056], + zoom: 12.5 + }), + }); + + this.scene = scene; + let fontFamily = 'iconfont'; + let fontPath = + '//at.alicdn.com/t/font_2534097_x6rsov3i1g.woff2?t=1622107341225'; + scene.addIconFont("icon", "") + scene.addFontFace(fontFamily, fontPath); + + let colors = [ + '#87CEFA', + '#00BFFF', + + '#7FFFAA', + '#00FF7F', + '#32CD32', + + '#F0E68C', + '#FFD700', + + '#FF7F50', + '#FF6347', + '#FF0000' + ] + + scene.on('loaded', () => { + + fetch('https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json') + .then((res) => res.json()) + .then((data) => { + + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3, + }) + .source(data) + .shape('fill') + .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) + // .color('count', [ + // '#87CEFA', + // '#00BFFF', + + // '#7FFFAA', + // '#00FF7F', + // '#32CD32', + + // '#F0E68C', + // '#FFD700', + + // '#FF7F50', + // '#FF6347', + // '#FF0000' + // ]) + .style({ + opacity: 0.8 + }) + scene.addLayer(filllayer); + + const linelayer = new LineLayer({ + zIndex: 5, + name: 'line2', + }) + .source(data) + .shape('line') + .size(1) + .color('#fff') + .style({ + opacity: 0.3 + }); + scene.addLayer(linelayer); + + const pointLayer = new PointLayer({ + zIndex: 10 + }) + .source(data) + .shape('icon', 'text') + .size(30) + .color('count', t => { + let c = Number(t.replace('℃', '')) + return colors[Math.floor(((c - 18)/16)*10)] + }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [30, 5], + padding: [2, 2], + fontFamily, + iconfont: true, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + + const tempertureLayer = new PointLayer({ + zIndex: 10 + }) + .source(data) + .shape('count', 'text') + .size(12) + // .color('count', [ + // '#87CEFA', + // '#00BFFF', + + // '#7FFFAA', + // '#00FF7F', + // '#32CD32', + + // '#F0E68C', + // '#FFD700', + + // '#FF7F50', + // '#FF6347', + // '#FF0000' + // ]) + .color('count', t => { + let c = Number(t.replace('℃', '')) + return colors[Math.floor(((c - 18)/16)*10)] + }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [35, 30], + padding: [1, 1], + }); + scene.addLayer(tempertureLayer); + + }) + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_polygon.tsx b/stories/Map/components/amap2demo_polygon.tsx index b58648acd8..b1cabbcbbc 100644 --- a/stories/Map/components/amap2demo_polygon.tsx +++ b/stories/Map/components/amap2demo_polygon.tsx @@ -1,21 +1,9 @@ -import { vec2, vec3 } from 'gl-matrix'; // @ts-ignore -import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { DrawPolygon } from '@antv/l7-draw'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; -import { mat4 } from 'gl-matrix'; - -function convertRGB2Hex(rgb: number[]) { - return ( - '#' + rgb.map((r) => ('0' + Math.floor(r).toString(16)).slice(-2)).join('') - ); -} - export default class Amap2demo_polygon extends React.Component { - private gui: dat.GUI; - private $stats: Node; private scene: Scene; public componentWillUnmount() { @@ -29,7 +17,7 @@ export default class Amap2demo_polygon extends React.Component { ); const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, // style: 'dark', center: [-44.40673828125, -18.375379094031825], diff --git a/stories/Map/components/amap2demo_polygon_extrude.tsx b/stories/Map/components/amap2demo_polygon_extrude.tsx index 3ef4ea5230..a0d515fe0f 100644 --- a/stories/Map/components/amap2demo_polygon_extrude.tsx +++ b/stories/Map/components/amap2demo_polygon_extrude.tsx @@ -2,7 +2,7 @@ import { vec2, vec3 } from 'gl-matrix'; // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; import { DrawPolygon } from '@antv/l7-draw'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; import { mat4 } from 'gl-matrix'; @@ -29,7 +29,7 @@ export default class Amap2demo_polygon_extrude extends React.Component { ); const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ pitch: 0, // style: 'dark', center: [-44.40673828125, -18.375379094031825], diff --git a/stories/Map/components/amap2demo_rasterlayer.tsx b/stories/Map/components/amap2demo_rasterlayer.tsx index cd3bf475bd..8b31dc45c2 100644 --- a/stories/Map/components/amap2demo_rasterlayer.tsx +++ b/stories/Map/components/amap2demo_rasterlayer.tsx @@ -1,5 +1,6 @@ -import { PointLayer, RasterLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +// @ts-ignore +import { RasterLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; // tslint:disable-next-line:no-submodule-imports // @ts-ignore @@ -36,7 +37,7 @@ export default class Amap2demo_rasterLayer extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap2({ + map: new GaodeMap({ center: [121.268, 30.3628], pitch: 0, style: 'dark', diff --git a/stories/Map/components/amap2demo_road.tsx b/stories/Map/components/amap2demo_road.tsx new file mode 100644 index 0000000000..260b007de2 --- /dev/null +++ b/stories/Map/components/amap2demo_road.tsx @@ -0,0 +1,138 @@ +// @ts-ignore +import { LineLayer, Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_road extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.1145, 30.221], + pitch: 50, + zoom: 16.8, + viewMode: '3D' + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json', + ) + .then((res) => res.json()) + .then((data) => { + + scene.addImage( + 'road', + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*haGlTpW2BQgAAAAAAAAAAAAAARQnAQ' + ); + + const layer = new LineLayer() + .source(data) + .size(10) + .shape('line') + .texture('road') + .color('rgb(20, 180, 90)') + .animate({ + interval: 1, // 间隔 + duration: 1, // 持续时间,延时 + trailLength: 2, // 流线长度 + }) + .style({ + lineTexture: true, // 开启线的贴图功能 + iconStep: 200, // 设置贴图纹理的间距 + }); + scene.addLayer(layer); + + scene.addImage( + 'start', + 'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg', + ); + scene.addImage( + 'visitor', + 'https://gw.alipayobjects.com/zos/bmw-prod/64db255d-b636-4929-b072-068e75178b23.svg', + ); + scene.addImage( + 'museum', + 'https://gw.alipayobjects.com/zos/bmw-prod/0630591d-64db-4057-a04d-d65f43aebf0f.svg', + ); + scene.addImage( + 'supermarket', + 'https://gw.alipayobjects.com/zos/bmw-prod/ab42799d-dea6-4d37-bd62-3ee3e06bf6c0.svg', + ); + scene.addImage( + 'tower', + 'https://gw.alipayobjects.com/zos/bmw-prod/6d27cf89-638c-432b-a8c4-cac289ee98a8.svg', + ); + scene.addImage( + 'end', + 'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg', + ); + const imageLayer = new PointLayer() + .source([{ + lng: 120.11025885601617, + lat: 30.22006389085372, + icon: 'start' + },{ + lng: 120.11123578376913, + lat: 30.220443561196277, + icon: 'visitor' + },{ + lng: 120.11408457779198, + lat: 30.22019805564678, + icon: 'museum' + },{ + lng: 120.11683172384723, + lat: 30.21875509667716, + icon: 'supermarket' + },{ + lng: 120.11945546294194, + lat: 30.218724022876376, + icon: 'tower' + },{ + lng: 120.1184189041221, + lat: 30.21783201718256, + icon: 'end' + } + ], { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('icon', ['start', 'visitor', 'museum', 'supermarket', 'tower', 'end']) + .size(35) + .style({ + offsets: [0, 20] + }) + scene.addLayer(imageLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_text.tsx b/stories/Map/components/amap2demo_text.tsx index ea0cafd48b..02a783e4bf 100644 --- a/stories/Map/components/amap2demo_text.tsx +++ b/stories/Map/components/amap2demo_text.tsx @@ -1,11 +1,7 @@ -import { vec2, vec3 } from 'gl-matrix'; // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; - -import { mat4 } from 'gl-matrix'; - export default class Amap2demo_text extends React.Component { // @ts-ignore private scene: Scene; @@ -15,19 +11,134 @@ export default class Amap2demo_text extends React.Component { } public async componentDidMount() { + let fontFamily = 'iconfont'; + let fontPath = + '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; + + // let style = document.createElement('style') + // style.type = "text/css" + // style.innerText = ` + // @font-face{ + // font-family: '${fontname}'; + // src: url('${fontpath}') format('woff2') + // }` + // document.getElementsByTagName('head')[0].appendChild(style) + var mask = [ + [ + [ + [110, 40], + [130, 40], + [130, 20], + [110, 20], + ], + ], + ]; + const scene = new Scene({ id: 'map', - map: new GaodeMap2({ - center: [120.19382669582967, 30.258134], + map: new GaodeMap({ + center: [120, 30.258134], pitch: 0, style: 'light', zoom: 3, + // viewMode: "3D", + // mask }), }); this.scene = scene; + scene.addIconFont("icon1", "") + // scene.addIconFont("icon2", "") + // scene.addIconFonts([ + // ['icon1', ''], + // ['icon2', ''], + // ]); + + scene.addFontFace(fontFamily, fontPath); scene.on('loaded', () => { - console.log('event test'); + + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('icon', 'text') + .size(12) + .color('w', ['#f00', '#f00', '#0f0']) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [-10, 0], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily, + // fontFamily: "Times New Roman", + iconfont: true, + // textAllowOverlap: true, + }); + scene.addLayer(pointLayer); + }) + + // https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json + // const pointIconFontLayer = new PointLayer({}) + // .source( + // [ + // { + // j: 140, + // w: 30, + // m: '', + // }, + // { + // j: 140, + // w: 32, + // m: '', + // }, + // { + // j: 140, + // w: 34, + // m: 'icon1', + // }, + // { + // j: 140, + // w: 36, + // m: 'icon2', + // }, + // ], + // { + // parser: { + // type: 'json', + // x: 'j', + // y: 'w', + // }, + // }, + // ) + // .shape('m', 'text') + // .size(12) + // .color('w', ['#f00', '#f00', '#0f0']) + // .style({ + // textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + // textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] + // spacing: 2, // 字符间距 + // padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + // stroke: '#ffffff', // 描边颜色 + // strokeWidth: 0.3, // 描边宽度 + // strokeOpacity: 1.0, + // fontFamily, + // // fontFamily: "Times New Roman", + // iconfont: true, + // textAllowOverlap: true, + // }); + // scene.addLayer(pointIconFontLayer); fetch( 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', @@ -55,7 +166,6 @@ export default class Amap2demo_text extends React.Component { strokeOpacity: 1.0, // textAllowOverlap: true }); - scene.addLayer(pointLayer); }); }); diff --git a/stories/Map/components/amap2demo_winds.tsx b/stories/Map/components/amap2demo_winds.tsx new file mode 100644 index 0000000000..3c89a569db --- /dev/null +++ b/stories/Map/components/amap2demo_winds.tsx @@ -0,0 +1,73 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_winds extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 0, + style: 'light', + center: [-74.006, 40.7128], + zoom: 2, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/7455fead-1dc0-458d-b91a-fb4cf99e701e.txt', + ) + .then((res) => res.text()) + .then((data) => { + const layer = new LineLayer({ blend: 'normal' }) + .source(data, { + parser: { + type: 'csv', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(1) + .shape('arc') + .color('#6495ED') + .animate({ + duration: 4, + interval: 0.2, + trailLength: 0.6, + }); + // .forward(false) + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amapdemo_extrude.tsx b/stories/Map/components/amapdemo_extrude.tsx index c3e0fe27dc..755bb866f0 100644 --- a/stories/Map/components/amapdemo_extrude.tsx +++ b/stories/Map/components/amapdemo_extrude.tsx @@ -1,6 +1,6 @@ // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMap2 } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; export default class Amapdemo_extrude extends React.Component { diff --git a/stories/Map/map.stories.tsx b/stories/Map/map.stories.tsx index f5431b913c..df8bbb326b 100644 --- a/stories/Map/map.stories.tsx +++ b/stories/Map/map.stories.tsx @@ -5,17 +5,27 @@ import Amap2demo from './components/amap2demo' import Amap2demo_extrude from './components/amap2demo_extrude' import Amapdemo_extrude from './components/amapdemo_extrude' import Amap2demo_text from './components/amap2demo_text' +import Amap2demo_iconfont from './components/amap2demo_iconfont'; import Amap2demo_image from './components/amap2demo_image' +import Amap2demo_winds from "./components/amap2demo_winds" + import Amap2demo_polygon from './components/amap2demo_polygon' import Amap2demo_polygon_extrude from './components/amap2demo_polygon_extrude' + import Amap2demo_arcLine from "./components/amap2demo_arcLine" import Amap2demo_arcLine3d from "./components/amap2demo_arcLine3d" import Amap2demo_arcLine_greatCircle from "./components/amap2demo_arcLine_greatCircle" +import Amap2demo_lineHeight from "./components/amap2demo_lineHeight" +import Amap2demo_lineDash from "./components/amap2demo_lineDash" +import Amap2demo_arcLineDir from "./components/amap2demo_arcLineDir" +import Amap2demo_lineStreet from './components/amap2demo_lineStreet'; +import Amap2demo_road from './components/amap2demo_road'; import Amap2demo_heatmap from "./components/amap2demo_heatmap" import Amap2demo_heatmap3D from "./components/amap2demo_heatmap3D" import Amap2demo_heatmap_hexagon from "./components/amap2demo_heatmap_hexagon" +import Amap2demo_heatmap_hexagon_world from './components/amap2demo_heatmap_hexagon_world'; import Amap2demo_heatmap_grid from "./components/amap2demo_heatmap_grid" import Amap2demo_imageLayer from "./components/amap2demo_imagelayer" @@ -24,6 +34,16 @@ import Amap2demo_rasterLayer from "./components/amap2demo_rasterlayer" import Amap2demo_citybuilding from "./components/amap2demo_citybuilding" +import Amap2demo_drilldown from "./components/amap2demo_drilldown" + +import Amap2demo_markerlayer from "./components/amap2demo_markerlayer" + +import Amap2demo_instance from "./components/amap2demo_instance" + +import Amap2demo_drawControl from "./components/amap2demo_drawControl" + +import Amap2demo_mesh from "./components/amap2demo_mesh" + // @ts-ignore storiesOf('地图方法', module) .add('高德地图 point/demo', () => ) @@ -31,16 +51,37 @@ storiesOf('地图方法', module) .add('高德地图 point/extrude', () => ) .add('高德地图2.0 point/extrude', () => ) .add('高德地图2.0 point/text', () => ) + .add('高德地图2.0 point/iconfont', () => ) .add('高德地图2.0 point/image', () => ) + .add('高德地图2.0 polygon', () => ) .add('高德地图2.0 polygon_extrude', () => ) + .add('高德地图2.0 line_arc', () => ) .add('高德地图2.0 line_arc3d', () => ) .add('高德地图2.0 line_arc3d_greatCircle', () => ) + .add('高德地图2.0 lineHeight', () => ) + .add('高德地图2.0 lineDash', () => ) + .add('高德地图2.0 line_arcDir', () => ) + .add('高德地图2.0 line_winds', () => ) + .add('高德地图2.0 line_Street', () => ) + .add('高德地图2.0 road', () => ) + .add('高德地图2.0 heatmap', () => ) .add('高德地图2.0 heatmap3D', () => ) .add('高德地图2.0 heatmap3D/hexagon', () => ) + .add('高德地图2.0 heatmap/hexagon/world', () => ) .add('高德地图2.0 heatmap3D/grid', () => ) .add('高德地图2.0 imageLayer', () => ) .add('高德地图2.0 rasterLayer', () => ) .add('高德地图2.0 citybuildLayer', () => ) + + .add('高德地图2.0 点击下钻', () => ) + + .add('高德地图2.0 Marker图层', () => ) + + .add('高德地图2.0 instance实例', () => ) + + .add('高德地图2.0 drawControl实例', () => ) + + .add('高德地图2.0 mesh实例', () => ) From 479b803404eeeb44904a398b39321bae2bf4384c Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Thu, 27 May 2021 19:55:06 +0800 Subject: [PATCH 5/9] feat: 2.4 beat versio --- docs/api/map.zh.md | 14 +- docs/api/scene.zh.md | 119 +++++---- .../animate/demo/animate_path_texture.js | 6 +- examples/line/path/demo/road_red.js | 4 +- examples/point/image/demo/road.js | 50 ++-- examples/point/scatter/demo/animatePoint.js | 22 +- examples/point/scatter/demo/dynamicScatter.js | 16 +- examples/point/text/demo/iconfont.js | 48 ++-- examples/point/text/demo/iconfonts.js | 238 +++++++++--------- examples/point/text/demo/temperture.js | 90 +++---- stories/Map/components/amap2demo_iconfont.tsx | 122 +++++---- stories/Map/components/amap2demo_mesh.tsx | 115 +++++---- stories/Map/components/amap2demo_road.tsx | 91 ++++--- stories/Map/components/amap2demo_text.tsx | 5 +- 14 files changed, 483 insertions(+), 457 deletions(-) diff --git a/docs/api/map.zh.md b/docs/api/map.zh.md index c2685e7b17..3c9e2b6b16 100644 --- a/docs/api/map.zh.md +++ b/docs/api/map.zh.md @@ -15,7 +15,7 @@ L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管 ### 引入 Map ```javascript -import { GaodeMap } from '@antv/l7-maps'; // 默认引入高德2.0 +import { GaodeMap } from '@antv/l7-maps'; // 默认引入高德2.0 import { GaodeMapV1 } from '@antv/l7-maps'; // 默认引入高德1.x 版本 import { Mapbox } from '@antv/l7-maps'; @@ -78,8 +78,8 @@ const scene = new Scene({ ```javascript const map = new AMap.Map('map', { viewMode: '3D', - resizeEnable: true, // 是否监控地图容器尺寸变化 - zoom: 11, // 初始化地图层级 + resizeEnable: true, // 是否监控地图容器尺寸变化 + zoom: 11, // 初始化地图层级 center: [116.397428, 39.90923], // 初始化地图中心点 }); const scene = new Scene({ @@ -101,10 +101,10 @@ const scene = new Scene({ ```javascript mapboxgl.accessToken = 'xxxx - token'; const map = new mapboxgl.Map({ - container: 'map', // container id - style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location - center: [-74.5, 40], // starting position [lng, lat] - zoom: 9, // starting zoom + container: 'map', // container id + style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location + center: [-74.5, 40], // starting position [lng, lat] + zoom: 9, // starting zoom }); const scene = new Scene({ diff --git a/docs/api/scene.zh.md b/docs/api/scene.zh.md index 5a7f4a3215..3cab6145dc 100644 --- a/docs/api/scene.zh.md +++ b/docs/api/scene.zh.md @@ -173,6 +173,7 @@ L7 Logo 的显示位置 默认左下角 增加图层对象 参数 : + - `layer` {ILayer} 图层对象 ```javascript @@ -184,10 +185,13 @@ scene.addLayer(layer); 获取对应的图层对象 参数 : + - `id` {string} + ```javascript scene.getLayer('layerID'); ``` + ### getLayers() 获取所有的地图图层 获取所有的地图图层 @@ -208,8 +212,7 @@ scene.getLayers(); scene.getLayerByName(name); // return Layer 图层对象 ``` - -### removeLayer 移除 layer 图层 +### removeLayer 移除 layer 图层 移除 layer 图层 @@ -261,17 +264,16 @@ scene.removeControl(ctl); - `name` { string } - ```javascript -const zoomControl = new Zoom({ // zoom 控件 +const zoomControl = new Zoom({ + // zoom 控件 name: 'z1', // 用户传入的控件名称(也可以不传入,该控件默认名称为 zoom) - position: 'topright' + position: 'topright', }); scene.getControlByName('z1'); ``` - ## 标记方法 ### addMarker(maker) 添加标记 @@ -284,22 +286,24 @@ scene.getControlByName('z1'); ```javascript const marker = new Marker({ - element: el + element: el, }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); scene.addMarker(marker); ``` ### addMarkerLayer(layer) 添加 Marker 统一管理图层 + 当用户需要添加许多个 Marker 实例时,为了方便管理可以使用 markerLayer 对象统一管理 参数 : -- `layer` { IMarkerLayer } 标记图层对象 +- `layer` { IMarkerLayer } 标记图层对象 ```javascript const markerLayer = new MarkerLayer(); scene.addMarkerLayer(markerLayer); ``` + [示例地址](/zh/examples/point/marker#markerlayer) ### removeMarkerLayer(layer) 移除标签图层 @@ -334,7 +338,6 @@ scene.getZoom(); return {float}   当前缩放等级 - ### getCenter() 获取地图中心 获取地图中心点 @@ -518,7 +521,6 @@ scene.fitBounds([ ]); ``` - ### exportMap 导出地图图片 导出地图,目前仅支持导出可视化层,不支持底图导出 @@ -536,6 +538,7 @@ scene 销毁方法,离开页面,或者不需要使用地图可以调用 ```javascript scene.destroy(); ``` + ## iconfont 映射支持 ### addIconFont(name, fontUnicode) 增加对数据中 unicode 的映射支持 @@ -548,37 +551,40 @@ scene.destroy(); - `fontUnicode` {string} ```javascript - scene.addIconFont("icon1", "") - scene.addIconFont("icon2", "") - scene.addFontFace(fontFamily, fontPath); - const pointIconFontLayer = new PointLayer({}) - .source( - [{ - j: 140, - w: 34, - m: 'icon1', - },{ - j: 140, - w: 36, - m: 'icon2', - }], - { - parser: { - type: 'json', - x: 'j', - y: 'w', - }, - }, - ) - .shape('m', 'text') - .size(12) - .color('w', ['#f00', '#f00', '#0f0']) - .style({ - fontFamily, - iconfont: true, - textAllowOverlap: true, - }); - scene.addLayer(pointIconFontLayer); +scene.addIconFont('icon1', ''); +scene.addIconFont('icon2', ''); +scene.addFontFace(fontFamily, fontPath); +const pointIconFontLayer = new PointLayer({}) + .source( + [ + { + j: 140, + w: 34, + m: 'icon1', + }, + { + j: 140, + w: 36, + m: 'icon2', + }, + ], + { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }, + ) + .shape('m', 'text') + .size(12) + .color('w', ['#f00', '#f00', '#0f0']) + .style({ + fontFamily, + iconfont: true, + textAllowOverlap: true, + }); +scene.addLayer(pointIconFontLayer); ``` ### addIconFonts(options) 同时传入多组 name - unicode 的键值对 @@ -586,14 +592,16 @@ scene.destroy(); 同时传入多组 name - unicode 的键值对 参数 : + - `options` { Array<[name, unicode]> } ```javascript - scene.addIconFonts([ - ['icon1', ''], - ['icon2', ''], - ]); +scene.addIconFonts([ + ['icon1', ''], + ['icon2', ''], +]); ``` + ## 全局资源 ### addImage(id, img) 全局中添加的图片资源 @@ -601,11 +609,17 @@ scene.destroy(); 在 L7 的图层对象可以使用在 scene 全局中添加的图片资源 参数 : + - `id` {string} - `img` {HTMLImageElement | File | string} + ```javascript -scene.addImage('02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg'); +scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', +); ``` + [示例地址](/zh/examples/gallery/animate#animate_path_texture) ### hasImage(id) 判断全局图片资源 @@ -613,9 +627,11 @@ scene.addImage('02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-41 判断是否已经在全局添加过相应的图片资源 参数 : + - `id` {string} + ```javascript -scene.hasImage('imageID') +scene.hasImage('imageID'); ``` ### removeImage(id) 全局删除图片资源 @@ -623,9 +639,11 @@ scene.hasImage('imageID') 从全局删除对应的图片资源 参数 : + - `id` {string} + ```javascript -scene.removeImage('imageID') +scene.removeImage('imageID'); ``` ### addFontFace(fontFamily, fontPath) 添加字体文件 @@ -633,11 +651,14 @@ scene.removeImage('imageID') 添加字体文件 参数 : + - `fontFamily` {string} 用户为自己定义的字体名称 - `fontPath` {string} 导入的文件地址 + ```javascript let fontFamily = 'iconfont'; -let fontPath = '//at.alicdn.com/t/font_2534097_iiet9d3nekn.woff2?t=1620444089776'; +let fontPath = + '//at.alicdn.com/t/font_2534097_iiet9d3nekn.woff2?t=1620444089776'; scene.addFontFace(fontFamily, fontPath); ``` diff --git a/examples/gallery/animate/demo/animate_path_texture.js b/examples/gallery/animate/demo/animate_path_texture.js index 72d2284bf9..199cbe9b08 100644 --- a/examples/gallery/animate/demo/animate_path_texture.js +++ b/examples/gallery/animate/demo/animate_path_texture.js @@ -13,7 +13,7 @@ const scene = new Scene({ scene.on('loaded', () => { scene.addImage( '02', - 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg' ); fetch( 'https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json' @@ -33,8 +33,8 @@ scene.on('loaded', () => { }) .style({ lineTexture: true, // 开启线的贴图功能 - iconStep: 100, // 设置贴图纹理的间距 - }) + iconStep: 100 // 设置贴图纹理的间距 + }); scene.addLayer(layer); }); }); diff --git a/examples/line/path/demo/road_red.js b/examples/line/path/demo/road_red.js index a7a5725614..85d0c17a83 100644 --- a/examples/line/path/demo/road_red.js +++ b/examples/line/path/demo/road_red.js @@ -9,12 +9,12 @@ import { const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [116.3956, 39.9392], + center: [ 116.3956, 39.9392 ], pitch: 0, zoom: 10, rotation: 0, style: 'amap://styles/light', - viewMode: '2D', + viewMode: '2D' }) }); scene.on('loaded', () => { diff --git a/examples/point/image/demo/road.js b/examples/point/image/demo/road.js index c4df662595..c2c67908c4 100644 --- a/examples/point/image/demo/road.js +++ b/examples/point/image/demo/road.js @@ -4,18 +4,18 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [120.115, 30.221], + center: [ 120.115, 30.221 ], pitch: 40, zoom: 16, - viewMode: '3D', + viewMode: '3D' }) }); scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json', + 'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json' ) - .then((res) => res.json()) - .then((data) => { + .then(res => res.json()) + .then(data => { scene.addImage( 'road', @@ -31,76 +31,76 @@ scene.on('loaded', () => { .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 - trailLength: 2, // 流线长度 + trailLength: 2 // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 - iconStep: 200, // 设置贴图纹理的间距 + iconStep: 200 // 设置贴图纹理的间距 }); scene.addLayer(layer); scene.addImage( 'start', - 'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg' ); scene.addImage( 'visitor', - 'https://gw.alipayobjects.com/zos/bmw-prod/64db255d-b636-4929-b072-068e75178b23.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/64db255d-b636-4929-b072-068e75178b23.svg' ); scene.addImage( 'museum', - 'https://gw.alipayobjects.com/zos/bmw-prod/0630591d-64db-4057-a04d-d65f43aebf0f.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/0630591d-64db-4057-a04d-d65f43aebf0f.svg' ); scene.addImage( 'supermarket', - 'https://gw.alipayobjects.com/zos/bmw-prod/ab42799d-dea6-4d37-bd62-3ee3e06bf6c0.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/ab42799d-dea6-4d37-bd62-3ee3e06bf6c0.svg' ); scene.addImage( 'tower', - 'https://gw.alipayobjects.com/zos/bmw-prod/6d27cf89-638c-432b-a8c4-cac289ee98a8.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/6d27cf89-638c-432b-a8c4-cac289ee98a8.svg' ); scene.addImage( 'end', - 'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg', + 'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg' ); const imageLayer = new PointLayer() .source([{ lng: 120.11025885601617, lat: 30.22006389085372, icon: 'start' - },{ + }, { lng: 120.11123578376913, lat: 30.220443561196277, icon: 'visitor' - },{ + }, { lng: 120.11408457779198, lat: 30.22019805564678, icon: 'museum' - },{ + }, { lng: 120.11683172384723, lat: 30.21875509667716, icon: 'supermarket' - },{ + }, { lng: 120.11945546294194, lat: 30.218724022876376, icon: 'tower' - },{ + }, { lng: 120.1184189041221, lat: 30.21783201718256, icon: 'end' } - ], { + ], { parser: { type: 'json', x: 'lng', - y: 'lat', - }, + y: 'lat' + } }) - .shape('icon', ['start', 'visitor', 'museum', 'supermarket', 'tower', 'end']) + .shape('icon', [ 'start', 'visitor', 'museum', 'supermarket', 'tower', 'end' ]) .size(35) .style({ - offsets: [0, 20] - }) + offsets: [ 0, 20 ] + }); scene.addLayer(imageLayer); }); -}); \ No newline at end of file +}); diff --git a/examples/point/scatter/demo/animatePoint.js b/examples/point/scatter/demo/animatePoint.js index 2d5171bb57..e6bb545790 100644 --- a/examples/point/scatter/demo/animatePoint.js +++ b/examples/point/scatter/demo/animatePoint.js @@ -5,23 +5,23 @@ const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', - center: [112, 23.69], - zoom: 2.5, + center: [ 112, 23.69 ], + zoom: 2.5 }) }); fetch( - 'https://gw.alipayobjects.com/os/basement_prod/9078fd36-ce8d-4ee2-91bc-605db8315fdf.csv', + 'https://gw.alipayobjects.com/os/basement_prod/9078fd36-ce8d-4ee2-91bc-605db8315fdf.csv' ) - .then((res) => res.text()) - .then((data) => { + .then(res => res.text()) + .then(data => { const pointLayer = new PointLayer({}) .source(data, { parser: { type: 'csv', x: 'Longitude', - y: 'Latitude', - }, + y: 'Latitude' + } }) .shape('circle') .active(true) @@ -30,15 +30,15 @@ fetch( .color('#ffa842') .style({ opacity: 1, - offsets: [40, 40], + offsets: [ 40, 40 ] }); const pointLayer2 = new PointLayer({}) .source(data, { parser: { type: 'csv', x: 'Longitude', - y: 'Latitude', - }, + y: 'Latitude' + } }) .shape('circle') .active(true) @@ -46,7 +46,7 @@ fetch( .size(50) .color('#f00') .style({ - opacity: 1, + opacity: 1 }); scene.addLayer(pointLayer); diff --git a/examples/point/scatter/demo/dynamicScatter.js b/examples/point/scatter/demo/dynamicScatter.js index ff7f0c0e89..34de1a999b 100644 --- a/examples/point/scatter/demo/dynamicScatter.js +++ b/examples/point/scatter/demo/dynamicScatter.js @@ -5,7 +5,7 @@ const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', - center: [120.19382669582967, 30.258134], + center: [ 120.19382669582967, 30.258134 ], zoom: 10 }) }); @@ -23,11 +23,11 @@ function pointOnCircle(angle) { type: 'Point', coordinates: [ 120.19382669582967 + Math.cos(angle) * radius, - 30.258134 + Math.sin(angle) * radius, - ], - }, - }, - ], + 30.258134 + Math.sin(angle) * radius + ] + } + } + ] }; } const layer = new PointLayer({}) @@ -39,7 +39,7 @@ const layer = new PointLayer({}) .style({ stroke: '#fff', strokeWidth: 2, - opacity: 1, + opacity: 1 }); scene.addLayer(layer); layer.setData(pointOnCircle(1000)); @@ -49,4 +49,4 @@ function animateMarker(timestamp) { scene.render(); requestAnimationFrame(animateMarker); } -animateMarker(0); \ No newline at end of file +animateMarker(0); diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js index 80842e25e8..185df6aee5 100644 --- a/examples/point/text/demo/iconfont.js +++ b/examples/point/text/demo/iconfont.js @@ -10,13 +10,13 @@ const scene = new Scene({ zoom: 3 }) }); -let fontFamily = 'iconfont'; -let fontPath = '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; +const fontFamily = 'iconfont'; +const fontPath = '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; scene.addFontFace(fontFamily, fontPath); -scene.addIconFont("icon1", "") +scene.addIconFont('icon1', ''); scene.on('loaded', () => { - fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') + fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') .then(res => res.json()) .then(data => { const pointLayer = new PointLayer({}) @@ -46,32 +46,32 @@ scene.on('loaded', () => { scene.addLayer(pointLayer); }); - fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json', - ) - .then((res) => res.json()) - .then((data) => { - const pointLayer = new PointLayer({}) + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json' + ) + .then(res => res.json()) + .then(data => { + const pointLayer = new PointLayer({}) .source(data.list, { - parser: { + parser: { type: 'json', x: 'j', - y: 'w', - }, + y: 'w' + } }) .shape('icon', 'text') .size(12) - .color('w', ['#f00', '#f00', '#0f0']) + .color('w', [ '#f00', '#f00', '#0f0' ]) .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [-10, 0], // 文本相对锚点的偏移量 [水平, 垂直] - spacing: 2, // 字符间距 - padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - stroke: '#ffffff', // 描边颜色 - fontFamily, - iconfont: true, - // textAllowOverlap: true, + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ -10, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + fontFamily, + iconfont: true + // textAllowOverlap: true, }); - scene.addLayer(pointLayer); - }) + scene.addLayer(pointLayer); + }); }); diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js index d4365206ab..3c0a772789 100644 --- a/examples/point/text/demo/iconfonts.js +++ b/examples/point/text/demo/iconfonts.js @@ -4,21 +4,21 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [120.5, 30.2], + center: [ 120.5, 30.2 ], pitch: 0, style: 'light', zoom: 8.5, - zooms: [8, 10], + zooms: [ 8, 10 ], viewMode: '2D' - }), + }) }); -let originData = [ +const originData = [ { lng: 120, lat: 30, iconType: 'sun', - iconColor: "#FFA500", - backgoundColor: "#00BFFF", + iconColor: '#FFA500', + backgoundColor: '#00BFFF', temperature: '28℃', weather: '晴朗' }, @@ -26,8 +26,8 @@ let originData = [ lng: 120.2, lat: 30.5, iconType: 'sun', - iconColor: "#FFA500", - backgoundColor: "#00BFFF", + iconColor: '#FFA500', + backgoundColor: '#00BFFF', temperature: '28℃', weather: '晴朗' }, @@ -35,8 +35,8 @@ let originData = [ lng: 121.5, lat: 31.4, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', weather: '多云' }, @@ -44,8 +44,8 @@ let originData = [ lng: 120, lat: 31, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', weather: '多云' }, @@ -53,8 +53,8 @@ let originData = [ lng: 120.6, lat: 30.8, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', weather: '多云' }, @@ -62,8 +62,8 @@ let originData = [ lng: 120.5, lat: 31.3, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', weather: '多云' }, @@ -71,8 +71,8 @@ let originData = [ lng: 121.3, lat: 30.2, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', weather: '小雨' }, @@ -80,8 +80,8 @@ let originData = [ lng: 121, lat: 30.5, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', weather: '小雨' }, @@ -89,8 +89,8 @@ let originData = [ lng: 120.6, lat: 30, iconType: 'middleRain', - iconColor: "#6495ED", - backgoundColor: "#326EA0", + iconColor: '#6495ED', + backgoundColor: '#326EA0', temperature: '24℃', weather: '中雨' }, @@ -98,8 +98,8 @@ let originData = [ lng: 120.2, lat: 29.7, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', weather: '小雨' }, @@ -107,8 +107,8 @@ let originData = [ lng: 121.7, lat: 29.8, iconType: 'middleRain', - iconColor: "#6495ED", - backgoundColor: "#326EA0", + iconColor: '#6495ED', + backgoundColor: '#326EA0', temperature: '24℃', weather: '中雨' }, @@ -116,110 +116,110 @@ let originData = [ lng: 121.5, lat: 30, iconType: 'hugeRain', - iconColor: "#4678D2", - backgoundColor: "#285A8C", + iconColor: '#4678D2', + backgoundColor: '#285A8C', temperature: '20℃', weather: '大雨' - }, + } ]; -let fontFamily = 'iconfont'; -let fontPath = '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076'; +const fontFamily = 'iconfont'; +const fontPath = '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076'; scene.addFontFace(fontFamily, fontPath); scene.addIconFonts([ - ['smallRain', ''], - ['middleRain', ''], - ['hugeRain', ''], - ['sun', ''], - ['cloud', ''], + [ 'smallRain', '' ], + [ 'middleRain', '' ], + [ 'hugeRain', '' ], + [ 'sun', '' ], + [ 'cloud', '' ] ]); scene.on('loaded', () => { - - const layer = new PointLayer() - .source(originData, { + + const layer = new PointLayer() + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat' + } + }) + .shape('circle') + .color('backgoundColor') + .size(40); + scene.addLayer(layer); + + + const pointIconFontLayer = new PointLayer({}) + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat' + } + } + ) + .shape('iconType', 'text') + .size(30) + .color('iconColor') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ 38, 10 ], // 文本相对锚点的偏移量 [水平, 垂直] + fontFamily, + iconfont: true, + textAllowOverlap: true + }); + scene.addLayer(pointIconFontLayer); + + const textLayer = new PointLayer({}) + .source(originData, + { parser: { type: 'json', x: 'lng', - y: 'lat', - }, - }) - .shape('circle') - .color('backgoundColor') - .size(40) - scene.addLayer(layer); + y: 'lat' + } + } + ) + .shape('temperature', 'text') + .size(10) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ 5, -55 ], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: 'Times New Roman', + textAllowOverlap: true + }); + scene.addLayer(textLayer); - - const pointIconFontLayer = new PointLayer({}) - .source(originData, { - parser: { - type: 'json', - x: 'lng', - y: 'lat', - } - }, - ) - .shape('iconType', 'text') - .size(30) - .color('iconColor') - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [38, 10], // 文本相对锚点的偏移量 [水平, 垂直] - fontFamily, - iconfont: true, - textAllowOverlap: true, - }); - scene.addLayer(pointIconFontLayer); - - const textLayer = new PointLayer({}) - .source(originData, - { - parser: { - type: 'json', - x: 'lng', - y: 'lat', - }, - }, - ) - .shape('temperature', 'text') - .size(10) - .color('#ffffff') - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [5, -55], // 文本相对锚点的偏移量 [水平, 垂直] - spacing: 2, // 字符间距 - padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - stroke: '#ffffff', // 描边颜色 - strokeWidth: 0.3, // 描边宽度 - strokeOpacity: 1.0, - fontFamily: "Times New Roman", - textAllowOverlap: true, - }); - scene.addLayer(textLayer); - - const textLayer2 = new PointLayer({}) - .source(originData, - { - parser: { - type: 'json', - x: 'lng', - y: 'lat' - }, - }, - ) - .shape('weather', 'text') - .size(14) - .color('#ffffff') - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [5, -15], // 文本相对锚点的偏移量 [水平, 垂直] - spacing: 2, // 字符间距 - padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - stroke: '#ffffff', // 描边颜色 - strokeWidth: 0.3, // 描边宽度 - strokeOpacity: 1.0, - fontFamily: "Times New Roman", - textAllowOverlap: true, - }); - scene.addLayer(textLayer2); + const textLayer2 = new PointLayer({}) + .source(originData, + { + parser: { + type: 'json', + x: 'lng', + y: 'lat' + } + } + ) + .shape('weather', 'text') + .size(14) + .color('#ffffff') + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ 5, -15 ], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily: 'Times New Roman', + textAllowOverlap: true + }); + scene.addLayer(textLayer2); }); diff --git a/examples/point/text/demo/temperture.js b/examples/point/text/demo/temperture.js index 487071489f..d9ee085cf6 100644 --- a/examples/point/text/demo/temperture.js +++ b/examples/point/text/demo/temperture.js @@ -6,19 +6,19 @@ const scene = new Scene({ map: new GaodeMap({ style: 'dark', pitch: 40, - center: [118.8, 32.056], + center: [ 118.8, 32.056 ], zoom: 12.5 }) }); -let fontFamily = 'iconfont'; -let fontPath = +const fontFamily = 'iconfont'; +const fontPath = '//at.alicdn.com/t/font_2534097_x6rsov3i1g.woff2?t=1622107341225'; - scene.addIconFont("icon", "") - scene.addFontFace(fontFamily, fontPath); +scene.addIconFont('icon', ''); +scene.addFontFace(fontFamily, fontPath); -let colors = [ - '#87CEFA', - '#00BFFF', +const colors = [ + '#87CEFA', + '#00BFFF', '#7FFFAA', '#00FF7F', @@ -30,28 +30,28 @@ let colors = [ '#FF7F50', '#FF6347', '#FF0000' -] +]; scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json') - .then((res) => res.json()) - .then((data) => { + .then(res => res.json()) + .then(data => { - const filllayer = new PolygonLayer({ - name: 'fill', - zIndex: 3, - }) - .source(data) - .shape('fill') - .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) - .style({ - opacity: 0.8 + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3 }) + .source(data) + .shape('fill') + .color('count', [ 'rgb(194, 143, 133)', 'rgb(148, 167, 192)' ]) + .style({ + opacity: 0.8 + }); scene.addLayer(filllayer); const linelayer = new LineLayer({ zIndex: 5, - name: 'line2', + name: 'line2' }) .source(data) .shape('line') @@ -60,24 +60,24 @@ scene.on('loaded', () => { .style({ opacity: 0.3 }); - scene.addLayer(linelayer); - - const pointLayer = new PointLayer({ - zIndex: 10 - }) + scene.addLayer(linelayer); + + const pointLayer = new PointLayer({ + zIndex: 10 + }) .source(data) .shape('icon', 'text') .size(30) .color('count', t => { - let c = Number(t.replace('℃', '')) - return colors[Math.floor(((c - 18)/16)*10)] + const c = Number(t.replace('℃', '')); + return colors[Math.floor(((c - 18) / 16) * 10)]; }) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [30, 5], - padding: [2, 2], + textOffset: [ 30, 5 ], + padding: [ 2, 2 ], fontFamily, - iconfont: true, + iconfont: true // textAllowOverlap: true }); scene.addLayer(pointLayer); @@ -85,19 +85,19 @@ scene.on('loaded', () => { const tempertureLayer = new PointLayer({ zIndex: 10 }) - .source(data) - .shape('count', 'text') - .size(12) - .color('count', t => { - let c = Number(t.replace('℃', '')) - return colors[Math.floor(((c - 18)/16)*10)] - }) - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [35, 30], - padding: [1, 1], - }); - scene.addLayer(tempertureLayer); + .source(data) + .shape('count', 'text') + .size(12) + .color('count', t => { + const c = Number(t.replace('℃', '')); + return colors[Math.floor(((c - 18) / 16) * 10)]; + }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [ 35, 30 ], + padding: [ 1, 1 ] + }); + scene.addLayer(tempertureLayer); - }) + }); }); diff --git a/stories/Map/components/amap2demo_iconfont.tsx b/stories/Map/components/amap2demo_iconfont.tsx index cfc52d23e2..a0db923df0 100644 --- a/stories/Map/components/amap2demo_iconfont.tsx +++ b/stories/Map/components/amap2demo_iconfont.tsx @@ -15,7 +15,6 @@ export default class Amap2demo_iconfont extends React.Component { let fontPath = '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076'; - const scene = new Scene({ id: 'map', map: new GaodeMap({ @@ -24,7 +23,7 @@ export default class Amap2demo_iconfont extends React.Component { style: 'normal', zoom: 9, zooms: [8, 10], - viewMode: '2D' + viewMode: '2D', }), }); this.scene = scene; @@ -44,109 +43,109 @@ export default class Amap2demo_iconfont extends React.Component { lng: 120, lat: 30, iconType: 'sun', - iconColor: "#FFA500", - backgoundColor: "#00BFFF", + iconColor: '#FFA500', + backgoundColor: '#00BFFF', temperature: '28℃', - weather: '晴朗' + weather: '晴朗', }, { lng: 120.2, lat: 30.5, iconType: 'sun', - iconColor: "#FFA500", - backgoundColor: "#00BFFF", + iconColor: '#FFA500', + backgoundColor: '#00BFFF', temperature: '28℃', - weather: '晴朗' + weather: '晴朗', }, { lng: 121.5, lat: 31.4, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', - weather: '多云' + weather: '多云', }, { lng: 120, lat: 31, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', - weather: '多云' + weather: '多云', }, { lng: 120.6, lat: 30.8, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', - weather: '多云' + weather: '多云', }, { lng: 120.5, lat: 31.3, iconType: 'cloud', - iconColor: "#F0F8FF", - backgoundColor: "#1E90FF", + iconColor: '#F0F8FF', + backgoundColor: '#1E90FF', temperature: '22℃', - weather: '多云' + weather: '多云', }, { lng: 121.3, lat: 30.2, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', - weather: '小雨' + weather: '小雨', }, { lng: 121, lat: 30.5, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', - weather: '小雨' + weather: '小雨', }, { lng: 120.6, lat: 30, iconType: 'middleRain', - iconColor: "#6495ED", - backgoundColor: "#326EA0", + iconColor: '#6495ED', + backgoundColor: '#326EA0', temperature: '24℃', - weather: '中雨' + weather: '中雨', }, { lng: 120.2, lat: 29.7, iconType: 'smallRain', - iconColor: "#6EA0FF", - backgoundColor: "#4678AA", + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', temperature: '22℃', - weather: '小雨' + weather: '小雨', }, { lng: 121.7, lat: 29.8, iconType: 'middleRain', - iconColor: "#6495ED", - backgoundColor: "#326EA0", + iconColor: '#6495ED', + backgoundColor: '#326EA0', temperature: '24℃', - weather: '中雨' + weather: '中雨', }, { lng: 121.5, lat: 30, iconType: 'hugeRain', - iconColor: "#4678D2", - backgoundColor: "#285A8C", + iconColor: '#4678D2', + backgoundColor: '#285A8C', temperature: '20℃', - weather: '大雨' + weather: '大雨', }, ]; @@ -160,19 +159,17 @@ export default class Amap2demo_iconfont extends React.Component { }) .shape('circle') .color('backgoundColor') - .size(40) + .size(40); scene.addLayer(layer); - const pointIconFontLayer = new PointLayer({}) .source(originData, { - parser: { - type: 'json', - x: 'lng', - y: 'lat', - } + parser: { + type: 'json', + x: 'lng', + y: 'lat', }, - ) + }) .shape('iconType', 'text') .size(30) .color('iconColor') @@ -186,15 +183,13 @@ export default class Amap2demo_iconfont extends React.Component { scene.addLayer(pointIconFontLayer); const textLayer = new PointLayer({}) - .source(originData, - { - parser: { - type: 'json', - x: 'lng', - y: 'lat', - }, + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', }, - ) + }) .shape('temperature', 'text') .size(10) .color('#ffffff') @@ -206,21 +201,19 @@ export default class Amap2demo_iconfont extends React.Component { stroke: '#ffffff', // 描边颜色 strokeWidth: 0.3, // 描边宽度 strokeOpacity: 1.0, - fontFamily: "Times New Roman", + fontFamily: 'Times New Roman', textAllowOverlap: true, }); scene.addLayer(textLayer); const textLayer2 = new PointLayer({}) - .source(originData, - { - parser: { - type: 'json', - x: 'lng', - y: 'lat' - }, + .source(originData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', }, - ) + }) .shape('weather', 'text') .size(14) .color('#ffffff') @@ -232,11 +225,10 @@ export default class Amap2demo_iconfont extends React.Component { stroke: '#ffffff', // 描边颜色 strokeWidth: 0.3, // 描边宽度 strokeOpacity: 1.0, - fontFamily: "Times New Roman", + fontFamily: 'Times New Roman', textAllowOverlap: true, }); scene.addLayer(textLayer2); - }); } diff --git a/stories/Map/components/amap2demo_mesh.tsx b/stories/Map/components/amap2demo_mesh.tsx index 045dd90d73..5b8674d242 100644 --- a/stories/Map/components/amap2demo_mesh.tsx +++ b/stories/Map/components/amap2demo_mesh.tsx @@ -17,20 +17,20 @@ export default class Amap2demo_mesh extends React.Component { style: 'dark', pitch: 40, center: [118.8, 32.056], - zoom: 12.5 + zoom: 12.5, }), }); - + this.scene = scene; let fontFamily = 'iconfont'; let fontPath = '//at.alicdn.com/t/font_2534097_x6rsov3i1g.woff2?t=1622107341225'; - scene.addIconFont("icon", "") - scene.addFontFace(fontFamily, fontPath); + scene.addIconFont('icon', ''); + scene.addFontFace(fontFamily, fontPath); let colors = [ - '#87CEFA', - '#00BFFF', + '#87CEFA', + '#00BFFF', '#7FFFAA', '#00FF7F', @@ -41,15 +41,15 @@ export default class Amap2demo_mesh extends React.Component { '#FF7F50', '#FF6347', - '#FF0000' - ] + '#FF0000', + ]; scene.on('loaded', () => { - - fetch('https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json') + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json', + ) .then((res) => res.json()) .then((data) => { - const filllayer = new PolygonLayer({ name: 'fill', zIndex: 3, @@ -58,8 +58,8 @@ export default class Amap2demo_mesh extends React.Component { .shape('fill') .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) // .color('count', [ - // '#87CEFA', - // '#00BFFF', + // '#87CEFA', + // '#00BFFF', // '#7FFFAA', // '#00FF7F', @@ -73,52 +73,52 @@ export default class Amap2demo_mesh extends React.Component { // '#FF0000' // ]) .style({ - opacity: 0.8 - }) - scene.addLayer(filllayer); + opacity: 0.8, + }); + scene.addLayer(filllayer); - const linelayer = new LineLayer({ - zIndex: 5, - name: 'line2', - }) - .source(data) - .shape('line') - .size(1) - .color('#fff') - .style({ - opacity: 0.3 - }); - scene.addLayer(linelayer); - - const pointLayer = new PointLayer({ - zIndex: 10 - }) - .source(data) - .shape('icon', 'text') - .size(30) - .color('count', t => { - let c = Number(t.replace('℃', '')) - return colors[Math.floor(((c - 18)/16)*10)] - }) - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [30, 5], - padding: [2, 2], - fontFamily, - iconfont: true, - // textAllowOverlap: true - }); - scene.addLayer(pointLayer); + const linelayer = new LineLayer({ + zIndex: 5, + name: 'line2', + }) + .source(data) + .shape('line') + .size(1) + .color('#fff') + .style({ + opacity: 0.3, + }); + scene.addLayer(linelayer); - const tempertureLayer = new PointLayer({ - zIndex: 10 + const pointLayer = new PointLayer({ + zIndex: 10, + }) + .source(data) + .shape('icon', 'text') + .size(30) + .color('count', (t) => { + let c = Number(t.replace('℃', '')); + return colors[Math.floor(((c - 18) / 16) * 10)]; }) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [30, 5], + padding: [2, 2], + fontFamily, + iconfont: true, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + + const tempertureLayer = new PointLayer({ + zIndex: 10, + }) .source(data) .shape('count', 'text') .size(12) // .color('count', [ - // '#87CEFA', - // '#00BFFF', + // '#87CEFA', + // '#00BFFF', // '#7FFFAA', // '#00FF7F', @@ -131,18 +131,17 @@ export default class Amap2demo_mesh extends React.Component { // '#FF6347', // '#FF0000' // ]) - .color('count', t => { - let c = Number(t.replace('℃', '')) - return colors[Math.floor(((c - 18)/16)*10)] + .color('count', (t) => { + let c = Number(t.replace('℃', '')); + return colors[Math.floor(((c - 18) / 16) * 10)]; }) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [35, 30], + textOffset: [35, 30], padding: [1, 1], }); scene.addLayer(tempertureLayer); - - }) + }); }); } diff --git a/stories/Map/components/amap2demo_road.tsx b/stories/Map/components/amap2demo_road.tsx index 260b007de2..ca7f5894d0 100644 --- a/stories/Map/components/amap2demo_road.tsx +++ b/stories/Map/components/amap2demo_road.tsx @@ -18,21 +18,20 @@ export default class Amap2demo_road extends React.Component { center: [120.1145, 30.221], pitch: 50, zoom: 16.8, - viewMode: '3D' + viewMode: '3D', }), }); this.scene = scene; - + scene.on('loaded', () => { fetch( 'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json', ) .then((res) => res.json()) .then((data) => { - scene.addImage( 'road', - 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*haGlTpW2BQgAAAAAAAAAAAAAARQnAQ' + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*haGlTpW2BQgAAAAAAAAAAAAAARQnAQ', ); const layer = new LineLayer() @@ -77,43 +76,59 @@ export default class Amap2demo_road extends React.Component { 'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg', ); const imageLayer = new PointLayer() - .source([{ - lng: 120.11025885601617, - lat: 30.22006389085372, - icon: 'start' - },{ - lng: 120.11123578376913, - lat: 30.220443561196277, - icon: 'visitor' - },{ - lng: 120.11408457779198, - lat: 30.22019805564678, - icon: 'museum' - },{ - lng: 120.11683172384723, - lat: 30.21875509667716, - icon: 'supermarket' - },{ - lng: 120.11945546294194, - lat: 30.218724022876376, - icon: 'tower' - },{ - lng: 120.1184189041221, - lat: 30.21783201718256, - icon: 'end' - } - ], { - parser: { - type: 'json', - x: 'lng', - y: 'lat', + .source( + [ + { + lng: 120.11025885601617, + lat: 30.22006389085372, + icon: 'start', + }, + { + lng: 120.11123578376913, + lat: 30.220443561196277, + icon: 'visitor', + }, + { + lng: 120.11408457779198, + lat: 30.22019805564678, + icon: 'museum', + }, + { + lng: 120.11683172384723, + lat: 30.21875509667716, + icon: 'supermarket', + }, + { + lng: 120.11945546294194, + lat: 30.218724022876376, + icon: 'tower', + }, + { + lng: 120.1184189041221, + lat: 30.21783201718256, + icon: 'end', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, }, - }) - .shape('icon', ['start', 'visitor', 'museum', 'supermarket', 'tower', 'end']) + ) + .shape('icon', [ + 'start', + 'visitor', + 'museum', + 'supermarket', + 'tower', + 'end', + ]) .size(35) .style({ - offsets: [0, 20] - }) + offsets: [0, 20], + }); scene.addLayer(imageLayer); }); }); diff --git a/stories/Map/components/amap2demo_text.tsx b/stories/Map/components/amap2demo_text.tsx index 02a783e4bf..3061d29f6c 100644 --- a/stories/Map/components/amap2demo_text.tsx +++ b/stories/Map/components/amap2demo_text.tsx @@ -46,7 +46,7 @@ export default class Amap2demo_text extends React.Component { }), }); this.scene = scene; - scene.addIconFont("icon1", "") + scene.addIconFont('icon1', ''); // scene.addIconFont("icon2", "") // scene.addIconFonts([ @@ -56,7 +56,6 @@ export default class Amap2demo_text extends React.Component { scene.addFontFace(fontFamily, fontPath); scene.on('loaded', () => { - fetch( 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json', ) @@ -87,7 +86,7 @@ export default class Amap2demo_text extends React.Component { // textAllowOverlap: true, }); scene.addLayer(pointLayer); - }) + }); // https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json // const pointIconFontLayer = new PointLayer({}) From 68f2123d51088c4d052d8a509fb6b2af28ddbf08 Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Mon, 31 May 2021 10:34:15 +0800 Subject: [PATCH 6/9] feat: l7 2.4 demo --- .../animate/demo/animate_path_texture.js | 6 +- examples/gallery/animate/demo/meta.json | 2 +- examples/point/text/demo/iconfont.js | 51 ++------ examples/point/text/demo/iconfonts.js | 40 ++++++- examples/point/text/demo/meta.json | 19 +-- examples/point/text/demo/temperture.js | 2 +- examples/point/text/demo/updown.js | 83 +++++++++++++ .../src/line/shaders/line_arc_frag.glsl | 11 ++ .../src/line/shaders/line_arc_vert.glsl | 31 +++++ .../Map/components/amap2demo_arcLineTex.tsx | 96 +++++++++++++++ stories/Map/components/amap2demo_mesh.tsx | 2 +- stories/Map/components/amap2demo_mesh2.tsx | 113 ++++++++++++++++++ stories/Map/components/amap2demo_road2.tsx | 75 ++++++++++++ stories/Map/map.stories.tsx | 6 + 14 files changed, 481 insertions(+), 56 deletions(-) create mode 100644 examples/point/text/demo/updown.js create mode 100644 stories/Map/components/amap2demo_arcLineTex.tsx create mode 100644 stories/Map/components/amap2demo_mesh2.tsx create mode 100644 stories/Map/components/amap2demo_road2.tsx diff --git a/examples/gallery/animate/demo/animate_path_texture.js b/examples/gallery/animate/demo/animate_path_texture.js index 199cbe9b08..a9571fae09 100644 --- a/examples/gallery/animate/demo/animate_path_texture.js +++ b/examples/gallery/animate/demo/animate_path_texture.js @@ -5,9 +5,9 @@ const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [ 120.19382669582967, 30.258134 ], - pitch: 0, - zoom: 16, - style: 'dark' + pitch: 20, + zoom: 18, + style: 'light' }) }); scene.on('loaded', () => { diff --git a/examples/gallery/animate/demo/meta.json b/examples/gallery/animate/demo/meta.json index c17d654ee2..314402cd46 100644 --- a/examples/gallery/animate/demo/meta.json +++ b/examples/gallery/animate/demo/meta.json @@ -7,7 +7,7 @@ { "filename": "animate_path_texture.js", "title": "路径贴图", - "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*TLt7RI9bAWMAAAAAAAAAAAAAARQnAQ" + "screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*0UrUTakTFQsAAAAAAAAAAAAAARQnAQ" }, { "filename": "animate_path.js", diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js index 185df6aee5..1cd6e3787d 100644 --- a/examples/point/text/demo/iconfont.js +++ b/examples/point/text/demo/iconfont.js @@ -4,48 +4,18 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [ 110, 36 ], + center: [ 115, 30 ], pitch: 0, style: 'light', - zoom: 3 + zoom: 6 }) }); const fontFamily = 'iconfont'; -const fontPath = '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; +const fontPath = '//at.alicdn.com/t/font_2534097_fcae9o2mxbv.woff2?t=1622200439140'; scene.addFontFace(fontFamily, fontPath); -scene.addIconFont('icon1', ''); +scene.addIconFont('icon1', ''); scene.on('loaded', () => { - fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') - .then(res => res.json()) - .then(data => { - const pointLayer = new PointLayer({}) - .source(data.list, { - parser: { - type: 'json', - x: 'j', - y: 'w' - } - }) - .shape('m', 'text') - .size(12) - // .rotate("j",()=>{ - // return Math.random()*3*(Math.random()>0.5?1:-1) - // }) - .color('w', [ '#0e0030', '#0e0030', '#0e0030' ]) - .style({ - textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [ 0, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] - spacing: 2, // 字符间距 - padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - stroke: '#ffffff', // 描边颜色 - strokeWidth: 0.3, // 描边宽度 - strokeOpacity: 1.0 - }); - - scene.addLayer(pointLayer); - }); - fetch( 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json' ) @@ -60,17 +30,16 @@ scene.on('loaded', () => { } }) .shape('icon', 'text') - .size(12) - .color('w', [ '#f00', '#f00', '#0f0' ]) + .size(20) + .color('w', ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac']) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [ -10, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] - spacing: 2, // 字符间距 - padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + textOffset: [ 40, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] + padding: [ 0, 0 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#ffffff', // 描边颜色 fontFamily, - iconfont: true - // textAllowOverlap: true, + iconfont: true, + textAllowOverlap: true, }); scene.addLayer(pointLayer); }); diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js index 3c0a772789..04b45c95f9 100644 --- a/examples/point/text/demo/iconfonts.js +++ b/examples/point/text/demo/iconfonts.js @@ -6,13 +6,49 @@ const scene = new Scene({ map: new GaodeMap({ center: [ 120.5, 30.2 ], pitch: 0, - style: 'light', + style: 'amap://styles/453e2f8e11603fc8f7548fe18959e9e9', zoom: 8.5, zooms: [ 8, 10 ], viewMode: '2D' }) }); const originData = [ + { + lng: 121.7, + lat: 30.6, + iconType: 'hugeRain', + iconColor: '#4678D2', + backgoundColor: '#285A8C', + temperature: '20℃', + weather: '大雨' + }, + { + lng: 119.2, + lat: 30., + iconType: 'smallRain', + iconColor: '#6EA0FF', + backgoundColor: '#4678AA', + temperature: '22℃', + weather: '小雨' + }, + { + lng: 119.67, + lat: 30.2, + iconType: 'sun', + iconColor: '#FFA500', + backgoundColor: '#00BFFF', + temperature: '28℃', + weather: '晴朗' + }, + { + lng: 119.63, + lat: 30.6, + iconType: 'sun', + iconColor: '#FFA500', + backgoundColor: '#00BFFF', + temperature: '28℃', + weather: '晴朗' + }, { lng: 120, lat: 30, @@ -145,7 +181,7 @@ scene.on('loaded', () => { }) .shape('circle') .color('backgoundColor') - .size(40); + .size(42); scene.addLayer(layer); diff --git a/examples/point/text/demo/meta.json b/examples/point/text/demo/meta.json index 981ce924ef..4a8437389d 100644 --- a/examples/point/text/demo/meta.json +++ b/examples/point/text/demo/meta.json @@ -11,10 +11,15 @@ }, { "filename": "iconfont.js", - "title": "文字图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*96iHTKybWYcAAAAAAAAAAAAAARQnAQ" + "title": "图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*jnPwQZsY-bEAAAAAAAAAAAAAARQnAQ" }, - { + { + "filename": "polygon_text.js", + "title": "面数据标注", + "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*rCFqRp3iQosAAAAAAAAAAABkARQnAQ" + }, + { "filename": "iconfonts.js", "title": "天气图标标注", "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*AouOQ4VYTJMAAAAAAAAAAAAAARQnAQ" @@ -22,12 +27,12 @@ { "filename": "temperture.js", "title": "气温图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*VFmxTqQc7v4AAAAAAAAAAAAAARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*spetRL1JnfsAAAAAAAAAAAAAARQnAQ" }, { - "filename": "polygon_text.js", - "title": "面数据标注", - "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*rCFqRp3iQosAAAAAAAAAAABkARQnAQ" + "filename": "updown.js", + "title": "走势图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*5E4DR4H8qDQAAAAAAAAAAAAAARQnAQ" } ] } diff --git a/examples/point/text/demo/temperture.js b/examples/point/text/demo/temperture.js index d9ee085cf6..d7c6726efd 100644 --- a/examples/point/text/demo/temperture.js +++ b/examples/point/text/demo/temperture.js @@ -45,7 +45,7 @@ scene.on('loaded', () => { .shape('fill') .color('count', [ 'rgb(194, 143, 133)', 'rgb(148, 167, 192)' ]) .style({ - opacity: 0.8 + opacity: 0.5 }); scene.addLayer(filllayer); diff --git a/examples/point/text/demo/updown.js b/examples/point/text/demo/updown.js new file mode 100644 index 0000000000..ffbc1ad15e --- /dev/null +++ b/examples/point/text/demo/updown.js @@ -0,0 +1,83 @@ +import { Scene, PointLayer, PolygonLayer, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; + +const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'dark', + pitch: 40, + center: [ 118.8, 32.056 ], + zoom: 12.5 + }) +}); +let fontFamily = 'iconfont'; +let fontPath = + '//at.alicdn.com/t/font_2534097_bl34aphh10n.woff2?t=1622180820063'; +scene.addIconFont('up', ''); +scene.addIconFont('down', ''); +scene.addFontFace(fontFamily, fontPath); + + +scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/41802695-0f7e-4a81-ab16-539c4e39df0d.json', + ) + .then((res) => res.json()) + .then((data) => { + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3, + }) + .source(data) + .shape('fill') + .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) + .style({ + opacity: 0.5, + }); + scene.addLayer(filllayer); + + const linelayer = new LineLayer({ + zIndex: 5, + name: 'line2', + }) + .source(data) + .shape('line') + .size(1) + .color('#fff') + .style({ + opacity: 0.3, + }); + scene.addLayer(linelayer); + + const pointLayer = new PointLayer({ + zIndex: 10, + }) + .source(data) + .shape('icon', 'text') + .size(15) + .color('count', n => n>0?'#0f0':"#f00") + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [30, 5], + padding: [2, 2], + fontFamily, + iconfont: true, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + + const textLayer = new PointLayer({ + zIndex: 10, + }) + .source(data) + .shape('count', 'text') + .size(12) + .color('count', n => n>0?'#0f0':"#f00") + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [40, 10], + padding: [1, 1], + }); + scene.addLayer(textLayer); + }); +}); diff --git a/packages/layers/src/line/shaders/line_arc_frag.glsl b/packages/layers/src/line/shaders/line_arc_frag.glsl index 6cbeda27a8..6751c2e880 100644 --- a/packages/layers/src/line/shaders/line_arc_frag.glsl +++ b/packages/layers/src/line/shaders/line_arc_frag.glsl @@ -35,5 +35,16 @@ void main() { alpha = smoothstep(0., 1., alpha); gl_FragColor.a *= alpha; } + + // if(u_line_texture == LineTexture) { // while load texture + // //v_u; // 水平 + // float v = length(v_offset)/(v_a); // 横向 + // vec2 uv= v_iconMapUV / u_textSize + vec2(v_u, v) / u_textSize * 64.; + // // gl_FragColor = vec4(v_u, v, 0.0, 1.0); + // // gl_FragColor = vec4(1.0, 0.0, 0.0, v_u); + // gl_FragColor = filterColor(gl_FragColor + texture2D(u_texture, uv)); + // } else { + // gl_FragColor = filterColor(gl_FragColor); + // } gl_FragColor = filterColor(gl_FragColor); } diff --git a/packages/layers/src/line/shaders/line_arc_vert.glsl b/packages/layers/src/line/shaders/line_arc_vert.glsl index 2b6f8a4308..bce49316d1 100644 --- a/packages/layers/src/line/shaders/line_arc_vert.glsl +++ b/packages/layers/src/line/shaders/line_arc_vert.glsl @@ -1,6 +1,7 @@ #define LineTypeSolid 0.0 #define LineTypeDash 1.0 #define Animate 0.0 +// #define LineTexture 1.0 attribute vec4 a_Color; attribute vec3 a_Position; attribute vec4 a_Instance; @@ -17,6 +18,15 @@ uniform float u_line_type: 0.0; uniform vec4 u_dash_array: [10.0, 5., 0, 0]; uniform float u_lineDir: 1.0; varying vec4 v_dash_array; + +// uniform float u_icon_step: 100; +// uniform float u_line_texture; +// varying float v_u; +// varying vec2 v_offset; +// varying float v_a; +// attribute vec2 a_iconMapUV; +// varying vec2 v_iconMapUV; + #pragma include "projection" #pragma include "project" #pragma include "picking" @@ -70,10 +80,12 @@ vec2 getNormal(vec2 line_clipspace, float offset_direction) { void main() { v_color = a_Color; + vec2 source = a_Instance.rg; vec2 target = a_Instance.ba; float segmentIndex = a_Position.x; float segmentRatio = getSegmentRatio(segmentIndex); + float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0)); float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir); if(u_line_type == LineTypeDash) { @@ -93,6 +105,25 @@ void main() { vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y)); + // if(LineTexture == u_line_texture) { // 开启贴图模式 + // v_iconMapUV = a_iconMapUV; + + // float arctotal_Distance = length(source - target); + // float pixelLen = project_pixel(u_icon_step); + // v_u = fract(segmentRatio * (floor(arctotal_Distance/pixelLen))); + // // v_u = fract(segmentIndex/(segmentNumber) * (2.0)); + // // v_u = fract(segmentIndex/(segmentNumber - 1.0) * 1.0 + 0.3); + // // v_u = fract(mod(1.0- v_distance_ratio, 0.2)* (1.0/ 0.5)); + // // v_u = fract(clamp(v_u, 0.0, 1.0)*2.0); + // // v_u = fract(((segmentIndex * indexDir) / (segmentNumber - 1.)) * (floor(arctotal_Distance/pixelLen))); + // // float s = 6.0; + // // float l = segmentNumber/s; + // // v_u = mod(segmentIndex, l) / (segmentNumber/s); + // v_a = project_pixel(a_Size); + // v_offset = offset + offset * sign(a_Position.y); + // } + + // gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x gl_Position = u_Mvp * (vec4(curr.xy + offset, 0, 1.0)); diff --git a/stories/Map/components/amap2demo_arcLineTex.tsx b/stories/Map/components/amap2demo_arcLineTex.tsx new file mode 100644 index 0000000000..81bdb7e8bc --- /dev/null +++ b/stories/Map/components/amap2demo_arcLineTex.tsx @@ -0,0 +1,96 @@ +// @ts-ignore +import { LineLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_arcLineTex extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 40, + center: [107.77791556935472, 35.443286920228644], + zoom: 2.9142882493605033, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + ); + + let data = [ + // { + // lng1: 91.111891, + // lat1: 40.662557, + // lng2: 120.342625, + // lat2: 37.373799, + // }, + // { + // lng1: 116.98242187499999, + // lat1: 43.004647127794435, + // lng2: 105.64453124999999, + // lat2: 28.998531814051795, + // }, + { + lng1: 75.76171875, + lat1: 36.31512514748051, + lng2: 46.23046874999999, + lat2: 52.802761415419674, + }, + ]; + + const layer = new LineLayer({ + blend: 'normal', + }) + .source(data, { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }) + .size(10) + .shape('arc') + // .texture('02') + .color('#8C1EB2') + .style({ + forward: false, + // lineTexture: true, // 开启线的贴图功能 + // iconStep: 100, // 设置贴图纹理的间距 + }) + .animate(true) + scene.addLayer(layer); + + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_mesh.tsx b/stories/Map/components/amap2demo_mesh.tsx index 5b8674d242..a3a939e9a6 100644 --- a/stories/Map/components/amap2demo_mesh.tsx +++ b/stories/Map/components/amap2demo_mesh.tsx @@ -73,7 +73,7 @@ export default class Amap2demo_mesh extends React.Component { // '#FF0000' // ]) .style({ - opacity: 0.8, + opacity: 0.5, }); scene.addLayer(filllayer); diff --git a/stories/Map/components/amap2demo_mesh2.tsx b/stories/Map/components/amap2demo_mesh2.tsx new file mode 100644 index 0000000000..3fc7b08659 --- /dev/null +++ b/stories/Map/components/amap2demo_mesh2.tsx @@ -0,0 +1,113 @@ +//@ts-ignore +import { PointLayer, Scene, PolygonLayer, LineLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; +export default class Amap2demo_mesh2 extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + style: 'dark', + pitch: 40, + center: [118.8, 32.056], + zoom: 12.5, + }), + }); + + this.scene = scene; + let fontFamily = 'iconfont'; + let fontPath = + '//at.alicdn.com/t/font_2534097_bl34aphh10n.woff2?t=1622180820063'; + scene.addIconFont('up', ''); + scene.addIconFont('down', ''); + scene.addFontFace(fontFamily, fontPath); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/41802695-0f7e-4a81-ab16-539c4e39df0d.json', + ) + .then((res) => res.json()) + .then((data) => { + const filllayer = new PolygonLayer({ + name: 'fill', + zIndex: 3, + }) + .source(data) + .shape('fill') + .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) + .style({ + opacity: 0.5, + }); + scene.addLayer(filllayer); + + const linelayer = new LineLayer({ + zIndex: 5, + name: 'line2', + }) + .source(data) + .shape('line') + .size(1) + .color('#fff') + .style({ + opacity: 0.3, + }); + scene.addLayer(linelayer); + + const pointLayer = new PointLayer({ + zIndex: 10, + }) + .source(data) + .shape('icon', 'text') + .size(15) + .color('count', n => n>0?'#0f0':"#f00") + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [30, 5], + padding: [2, 2], + fontFamily, + iconfont: true, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + + const textLayer = new PointLayer({ + zIndex: 10, + }) + .source(data) + .shape('count', 'text') + .size(12) + .color('count', n => n>0?'#0f0':"#f00") + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [40, 10], + padding: [1, 1], + }); + scene.addLayer(textLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/components/amap2demo_road2.tsx b/stories/Map/components/amap2demo_road2.tsx new file mode 100644 index 0000000000..30c7a2ee88 --- /dev/null +++ b/stories/Map/components/amap2demo_road2.tsx @@ -0,0 +1,75 @@ +// @ts-ignore +import { LineLayer, Scene, PointLayer } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Amap2demo_road2 extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.165, 30.25], + pitch: 50, + zoom: 16.8, + viewMode: '3D', + }), + }); + this.scene = scene; + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', + ) + .then((res) => res.json()) + .then((data) => { + scene.addImage( + '02', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + ); + + const layer = new LineLayer({}) + .source(data) + .size(5) + .shape('line') + .texture('02') + // .color('#ccc') + .color('rgb(20, 180, 90)') + // .animate({ + // interval: 1, // 间隔 + // duration: 1, // 持续时间,延时 + // trailLength: 2, // 流线长度 + // }) + .style({ + // opacity: 0.5, + lineTexture: true, // 开启线的贴图功能 + iconStep: 80, // 设置贴图纹理的间距 + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/map.stories.tsx b/stories/Map/map.stories.tsx index df8bbb326b..22f5347bf0 100644 --- a/stories/Map/map.stories.tsx +++ b/stories/Map/map.stories.tsx @@ -19,8 +19,10 @@ import Amap2demo_arcLine_greatCircle from "./components/amap2demo_arcLine_greatC import Amap2demo_lineHeight from "./components/amap2demo_lineHeight" import Amap2demo_lineDash from "./components/amap2demo_lineDash" import Amap2demo_arcLineDir from "./components/amap2demo_arcLineDir" +import Amap2demo_arcLineTex from './components/amap2demo_arcLineTex'; import Amap2demo_lineStreet from './components/amap2demo_lineStreet'; import Amap2demo_road from './components/amap2demo_road'; +import Amap2demo_road2 from './components/amap2demo_road2'; import Amap2demo_heatmap from "./components/amap2demo_heatmap" import Amap2demo_heatmap3D from "./components/amap2demo_heatmap3D" @@ -43,6 +45,7 @@ import Amap2demo_instance from "./components/amap2demo_instance" import Amap2demo_drawControl from "./components/amap2demo_drawControl" import Amap2demo_mesh from "./components/amap2demo_mesh" +import Amap2demo_mesh2 from "./components/amap2demo_mesh2" // @ts-ignore storiesOf('地图方法', module) @@ -63,9 +66,11 @@ storiesOf('地图方法', module) .add('高德地图2.0 lineHeight', () => ) .add('高德地图2.0 lineDash', () => ) .add('高德地图2.0 line_arcDir', () => ) + .add('高德地图2.0 line_arcTex', () => ) .add('高德地图2.0 line_winds', () => ) .add('高德地图2.0 line_Street', () => ) .add('高德地图2.0 road', () => ) + .add('高德地图2.0 road2', () => ) .add('高德地图2.0 heatmap', () => ) .add('高德地图2.0 heatmap3D', () => ) @@ -85,3 +90,4 @@ storiesOf('地图方法', module) .add('高德地图2.0 drawControl实例', () => ) .add('高德地图2.0 mesh实例', () => ) + .add('高德地图2.0 mesh实例2', () => ) From 6f06a381ec0575a726fe3ab48f3c2d0eeda453e2 Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Mon, 31 May 2021 10:37:14 +0800 Subject: [PATCH 7/9] style: code style change --- examples/point/text/demo/iconfont.js | 4 +- examples/point/text/demo/iconfonts.js | 2 +- examples/point/text/demo/updown.js | 38 +++++++++---------- .../Map/components/amap2demo_arcLineTex.tsx | 3 +- stories/Map/components/amap2demo_mesh2.tsx | 4 +- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js index 1cd6e3787d..7e902a132f 100644 --- a/examples/point/text/demo/iconfont.js +++ b/examples/point/text/demo/iconfont.js @@ -31,7 +31,7 @@ scene.on('loaded', () => { }) .shape('icon', 'text') .size(20) - .color('w', ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac']) + .color('w', [ '#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac' ]) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [ 40, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] @@ -39,7 +39,7 @@ scene.on('loaded', () => { stroke: '#ffffff', // 描边颜色 fontFamily, iconfont: true, - textAllowOverlap: true, + textAllowOverlap: true }); scene.addLayer(pointLayer); }); diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js index 04b45c95f9..495d21c802 100644 --- a/examples/point/text/demo/iconfonts.js +++ b/examples/point/text/demo/iconfonts.js @@ -24,7 +24,7 @@ const originData = [ }, { lng: 119.2, - lat: 30., + lat: 30.0, iconType: 'smallRain', iconColor: '#6EA0FF', backgoundColor: '#4678AA', diff --git a/examples/point/text/demo/updown.js b/examples/point/text/demo/updown.js index ffbc1ad15e..876b8cf0b7 100644 --- a/examples/point/text/demo/updown.js +++ b/examples/point/text/demo/updown.js @@ -10,8 +10,8 @@ const scene = new Scene({ zoom: 12.5 }) }); -let fontFamily = 'iconfont'; -let fontPath = +const fontFamily = 'iconfont'; +const fontPath = '//at.alicdn.com/t/font_2534097_bl34aphh10n.woff2?t=1622180820063'; scene.addIconFont('up', ''); scene.addIconFont('down', ''); @@ -20,63 +20,63 @@ scene.addFontFace(fontFamily, fontPath); scene.on('loaded', () => { fetch( - 'https://gw.alipayobjects.com/os/bmw-prod/41802695-0f7e-4a81-ab16-539c4e39df0d.json', + 'https://gw.alipayobjects.com/os/bmw-prod/41802695-0f7e-4a81-ab16-539c4e39df0d.json' ) - .then((res) => res.json()) - .then((data) => { + .then(res => res.json()) + .then(data => { const filllayer = new PolygonLayer({ name: 'fill', - zIndex: 3, + zIndex: 3 }) .source(data) .shape('fill') - .color('count', ['rgb(194, 143, 133)', 'rgb(148, 167, 192)']) + .color('count', [ 'rgb(194, 143, 133)', 'rgb(148, 167, 192)' ]) .style({ - opacity: 0.5, + opacity: 0.5 }); scene.addLayer(filllayer); const linelayer = new LineLayer({ zIndex: 5, - name: 'line2', + name: 'line2' }) .source(data) .shape('line') .size(1) .color('#fff') .style({ - opacity: 0.3, + opacity: 0.3 }); scene.addLayer(linelayer); const pointLayer = new PointLayer({ - zIndex: 10, + zIndex: 10 }) .source(data) .shape('icon', 'text') .size(15) - .color('count', n => n>0?'#0f0':"#f00") + .color('count', n => (n > 0 ? '#0f0' : '#f00')) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [30, 5], - padding: [2, 2], + textOffset: [ 30, 5 ], + padding: [ 2, 2 ], fontFamily, - iconfont: true, + iconfont: true // textAllowOverlap: true }); scene.addLayer(pointLayer); const textLayer = new PointLayer({ - zIndex: 10, + zIndex: 10 }) .source(data) .shape('count', 'text') .size(12) - .color('count', n => n>0?'#0f0':"#f00") + .color('count', n => (n > 0 ? '#0f0' : '#f00')) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [40, 10], - padding: [1, 1], + textOffset: [ 40, 10 ], + padding: [ 1, 1 ] }); scene.addLayer(textLayer); }); diff --git a/stories/Map/components/amap2demo_arcLineTex.tsx b/stories/Map/components/amap2demo_arcLineTex.tsx index 81bdb7e8bc..0b90ccbd8f 100644 --- a/stories/Map/components/amap2demo_arcLineTex.tsx +++ b/stories/Map/components/amap2demo_arcLineTex.tsx @@ -71,9 +71,8 @@ export default class Amap2demo_arcLineTex extends React.Component { // lineTexture: true, // 开启线的贴图功能 // iconStep: 100, // 设置贴图纹理的间距 }) - .animate(true) + .animate(true); scene.addLayer(layer); - }); } diff --git a/stories/Map/components/amap2demo_mesh2.tsx b/stories/Map/components/amap2demo_mesh2.tsx index 3fc7b08659..b1818a97e2 100644 --- a/stories/Map/components/amap2demo_mesh2.tsx +++ b/stories/Map/components/amap2demo_mesh2.tsx @@ -66,7 +66,7 @@ export default class Amap2demo_mesh2 extends React.Component { .source(data) .shape('icon', 'text') .size(15) - .color('count', n => n>0?'#0f0':"#f00") + .color('count', (n) => (n > 0 ? '#0f0' : '#f00')) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [30, 5], @@ -83,7 +83,7 @@ export default class Amap2demo_mesh2 extends React.Component { .source(data) .shape('count', 'text') .size(12) - .color('count', n => n>0?'#0f0':"#f00") + .color('count', (n) => (n > 0 ? '#0f0' : '#f00')) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [40, 10], From 9dd399351995f3535466982f7b39bf520275685c Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Mon, 31 May 2021 20:04:34 +0800 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=E6=A1=88=E4=BE=8Bdemo=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/point/text/demo/iconfont.js | 9 ++--- examples/point/text/demo/iconfonts.js | 39 +++++++++++++--------- examples/point/text/demo/meta.json | 16 ++++----- examples/point/text/demo/temperture.js | 4 +-- examples/point/text/demo/updown.js | 4 +-- stories/3D_Model/Components/amap_three.tsx | 5 +-- stories/3D_Model/model.stories.tsx | 2 +- stories/Map/components/mapCenter.tsx | 4 +-- 8 files changed, 46 insertions(+), 37 deletions(-) diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js index 7e902a132f..ace6447a89 100644 --- a/examples/point/text/demo/iconfont.js +++ b/examples/point/text/demo/iconfont.js @@ -4,10 +4,11 @@ import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [ 115, 30 ], + center: [ 110, 30 ], pitch: 0, - style: 'light', - zoom: 6 + // style: 'light', + style: 'amap://styles/453e2f8e11603fc8f7548fe18959e9e9', + zoom: 5 }) }); const fontFamily = 'iconfont'; @@ -31,7 +32,7 @@ scene.on('loaded', () => { }) .shape('icon', 'text') .size(20) - .color('w', [ '#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac' ]) + .color('w', ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99']) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [ 40, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js index 495d21c802..6a68dacc95 100644 --- a/examples/point/text/demo/iconfonts.js +++ b/examples/point/text/demo/iconfonts.js @@ -12,13 +12,20 @@ const scene = new Scene({ viewMode: '2D' }) }); +const dataColor = { + bigRainBC: "#285A8C", + middleRainBC: "#326EA0", + smallRainBC: "#4678AA", + sunBC: "#00BFFF", + cloudBC: "#1E90FF" +} const originData = [ { lng: 121.7, lat: 30.6, iconType: 'hugeRain', iconColor: '#4678D2', - backgoundColor: '#285A8C', + backgoundColor: dataColor.bigRainBC, temperature: '20℃', weather: '大雨' }, @@ -27,7 +34,7 @@ const originData = [ lat: 30.0, iconType: 'smallRain', iconColor: '#6EA0FF', - backgoundColor: '#4678AA', + backgoundColor: dataColor.smallRainBC, temperature: '22℃', weather: '小雨' }, @@ -36,7 +43,7 @@ const originData = [ lat: 30.2, iconType: 'sun', iconColor: '#FFA500', - backgoundColor: '#00BFFF', + backgoundColor: dataColor.sunBC, temperature: '28℃', weather: '晴朗' }, @@ -45,7 +52,7 @@ const originData = [ lat: 30.6, iconType: 'sun', iconColor: '#FFA500', - backgoundColor: '#00BFFF', + backgoundColor: dataColor.sunBC, temperature: '28℃', weather: '晴朗' }, @@ -54,7 +61,7 @@ const originData = [ lat: 30, iconType: 'sun', iconColor: '#FFA500', - backgoundColor: '#00BFFF', + backgoundColor: dataColor.sunBC, temperature: '28℃', weather: '晴朗' }, @@ -63,7 +70,7 @@ const originData = [ lat: 30.5, iconType: 'sun', iconColor: '#FFA500', - backgoundColor: '#00BFFF', + backgoundColor: dataColor.sunBC, temperature: '28℃', weather: '晴朗' }, @@ -72,7 +79,7 @@ const originData = [ lat: 31.4, iconType: 'cloud', iconColor: '#F0F8FF', - backgoundColor: '#1E90FF', + backgoundColor: dataColor.cloudBC, temperature: '22℃', weather: '多云' }, @@ -81,7 +88,7 @@ const originData = [ lat: 31, iconType: 'cloud', iconColor: '#F0F8FF', - backgoundColor: '#1E90FF', + backgoundColor: dataColor.cloudBC, temperature: '22℃', weather: '多云' }, @@ -90,7 +97,7 @@ const originData = [ lat: 30.8, iconType: 'cloud', iconColor: '#F0F8FF', - backgoundColor: '#1E90FF', + backgoundColor: dataColor.cloudBC, temperature: '22℃', weather: '多云' }, @@ -99,7 +106,7 @@ const originData = [ lat: 31.3, iconType: 'cloud', iconColor: '#F0F8FF', - backgoundColor: '#1E90FF', + backgoundColor: dataColor.cloudBC, temperature: '22℃', weather: '多云' }, @@ -108,7 +115,7 @@ const originData = [ lat: 30.2, iconType: 'smallRain', iconColor: '#6EA0FF', - backgoundColor: '#4678AA', + backgoundColor: dataColor.smallRainBC, temperature: '22℃', weather: '小雨' }, @@ -117,7 +124,7 @@ const originData = [ lat: 30.5, iconType: 'smallRain', iconColor: '#6EA0FF', - backgoundColor: '#4678AA', + backgoundColor: dataColor.smallRainBC, temperature: '22℃', weather: '小雨' }, @@ -126,7 +133,7 @@ const originData = [ lat: 30, iconType: 'middleRain', iconColor: '#6495ED', - backgoundColor: '#326EA0', + backgoundColor: dataColor.middleRainBC, temperature: '24℃', weather: '中雨' }, @@ -135,7 +142,7 @@ const originData = [ lat: 29.7, iconType: 'smallRain', iconColor: '#6EA0FF', - backgoundColor: '#4678AA', + backgoundColor: dataColor.smallRainBC, temperature: '22℃', weather: '小雨' }, @@ -144,7 +151,7 @@ const originData = [ lat: 29.8, iconType: 'middleRain', iconColor: '#6495ED', - backgoundColor: '#326EA0', + backgoundColor: dataColor.middleRainBC, temperature: '24℃', weather: '中雨' }, @@ -153,7 +160,7 @@ const originData = [ lat: 30, iconType: 'hugeRain', iconColor: '#4678D2', - backgoundColor: '#285A8C', + backgoundColor: dataColor.bigRainBC, temperature: '20℃', weather: '大雨' } diff --git a/examples/point/text/demo/meta.json b/examples/point/text/demo/meta.json index 4a8437389d..7a64d0bc4b 100644 --- a/examples/point/text/demo/meta.json +++ b/examples/point/text/demo/meta.json @@ -9,30 +9,30 @@ "title": "点数据标注", "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*7blvQ4v7Q1UAAAAAAAAAAABkARQnAQ" }, - { - "filename": "iconfont.js", - "title": "图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*jnPwQZsY-bEAAAAAAAAAAAAAARQnAQ" - }, { "filename": "polygon_text.js", "title": "面数据标注", "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*rCFqRp3iQosAAAAAAAAAAABkARQnAQ" }, + { + "filename": "iconfont.js", + "title": "图标标注", + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*8PfqQ6-lQ0EAAAAAAAAAAAAAARQnAQ" + }, { "filename": "iconfonts.js", "title": "天气图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*AouOQ4VYTJMAAAAAAAAAAAAAARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*JAhxTaabap4AAAAAAAAAAAAAARQnAQ" }, { "filename": "temperture.js", "title": "气温图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*spetRL1JnfsAAAAAAAAAAAAAARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*36umQaf_hVEAAAAAAAAAAAAAARQnAQ" }, { "filename": "updown.js", "title": "走势图标标注", - "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*5E4DR4H8qDQAAAAAAAAAAAAAARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*P5plS5ZsYZkAAAAAAAAAAAAAARQnAQ" } ] } diff --git a/examples/point/text/demo/temperture.js b/examples/point/text/demo/temperture.js index d7c6726efd..4bf45f9a84 100644 --- a/examples/point/text/demo/temperture.js +++ b/examples/point/text/demo/temperture.js @@ -43,9 +43,9 @@ scene.on('loaded', () => { }) .source(data) .shape('fill') - .color('count', [ 'rgb(194, 143, 133)', 'rgb(148, 167, 192)' ]) + .color('count', ['#f2f0f7','#dadaeb','#bcbddc','#9e9ac8','#756bb1','#54278f']) .style({ - opacity: 0.5 + opacity: 0.6 }); scene.addLayer(filllayer); diff --git a/examples/point/text/demo/updown.js b/examples/point/text/demo/updown.js index 876b8cf0b7..33fd94432d 100644 --- a/examples/point/text/demo/updown.js +++ b/examples/point/text/demo/updown.js @@ -30,9 +30,9 @@ scene.on('loaded', () => { }) .source(data) .shape('fill') - .color('count', [ 'rgb(194, 143, 133)', 'rgb(148, 167, 192)' ]) + .color('count', ['#f2f0f7','#dadaeb','#bcbddc','#9e9ac8','#756bb1','#54278f']) .style({ - opacity: 0.5 + opacity: 0.6 }); scene.addLayer(filllayer); diff --git a/stories/3D_Model/Components/amap_three.tsx b/stories/3D_Model/Components/amap_three.tsx index c63957acd3..8288ebc056 100644 --- a/stories/3D_Model/Components/amap_three.tsx +++ b/stories/3D_Model/Components/amap_three.tsx @@ -1,5 +1,5 @@ import { Scene } from '@antv/l7'; -import { GaodeMap, Mapbox } from '@antv/l7-maps'; +import { GaodeMap, Mapbox, GaodeMapV1 } from '@antv/l7-maps'; import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import * as React from 'react'; // import { DirectionalLight, Scene as ThreeScene } from 'three'; @@ -23,7 +23,8 @@ export default class GlTFThreeJSDemo extends React.Component { const scene = new Scene({ id: 'map', - map: new GaodeMap({ + // map: new GaodeMap({ + map: new GaodeMapV1({ center: [111.4453125, 32.84267363195431], pitch: 45, rotation: 30, diff --git a/stories/3D_Model/model.stories.tsx b/stories/3D_Model/model.stories.tsx index 1da45ee792..b031ad6727 100644 --- a/stories/3D_Model/model.stories.tsx +++ b/stories/3D_Model/model.stories.tsx @@ -6,5 +6,5 @@ import ThreeRender from './Components/threeRender'; storiesOf('3D 模型', module) .add('ThreeJS Render', () => , {}) - .add('高德模型', () => , {}) + .add('高德模型1.x', () => , {}) .add('Mapbox模型', () => , {}); diff --git a/stories/Map/components/mapCenter.tsx b/stories/Map/components/mapCenter.tsx index 0018b15100..e11654a232 100644 --- a/stories/Map/components/mapCenter.tsx +++ b/stories/Map/components/mapCenter.tsx @@ -1,6 +1,6 @@ // @ts-ignore import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; -import { GaodeMap } from '@antv/l7-maps'; +import { GaodeMap, GaodeMapV1 } from '@antv/l7-maps'; import * as React from 'react'; export default class GaodeMapComponent extends React.Component { @@ -14,7 +14,7 @@ export default class GaodeMapComponent extends React.Component { public async componentDidMount() { const scene = new Scene({ id: 'map', - map: new GaodeMap({ + map: new GaodeMapV1({ center: [121.107846, 30.267069], pitch: 0, style: 'normal', From e17977b8e00f5fc472d2d6c652bb7a4df623d237 Mon Sep 17 00:00:00 2001 From: 2912401452 <2912401452@qq.com> Date: Mon, 31 May 2021 20:39:15 +0800 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E5=AE=98?= =?UTF-8?q?=E7=BD=91=E6=96=87=E6=A1=A3=EF=BC=9AboxSelect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api/layer/layer.zh.md | 14 ++ examples/point/text/demo/iconfont.js | 2 +- examples/point/text/demo/iconfonts.js | 12 +- examples/point/text/demo/temperture.js | 2 +- examples/point/text/demo/updown.js | 2 +- packages/component/src/control/BaseControl.ts | 1 - stories/Map/components/amap2demo_text.tsx | 51 +------ .../Map/components/amap2demo_textSelect.tsx | 126 ++++++++++++++++++ stories/Map/map.stories.tsx | 2 + 9 files changed, 152 insertions(+), 60 deletions(-) create mode 100644 stories/Map/components/amap2demo_textSelect.tsx diff --git a/docs/api/layer/layer.zh.md b/docs/api/layer/layer.zh.md index aaae44fbe8..489937443e 100644 --- a/docs/api/layer/layer.zh.md +++ b/docs/api/layer/layer.zh.md @@ -590,3 +590,17 @@ layer.on('inited', (option) => {}); - target 当前 layer - type 事件类型 + +## 图层框选 + +### boxSelect + +参数 option +- box [x1: number, y1: number, x2: number, y2: number] 相较于 +- cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature + +```javascript +layer.boxSelect(box, cb); +// (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 +// cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 +``` diff --git a/examples/point/text/demo/iconfont.js b/examples/point/text/demo/iconfont.js index ace6447a89..8c0818cfc1 100644 --- a/examples/point/text/demo/iconfont.js +++ b/examples/point/text/demo/iconfont.js @@ -32,7 +32,7 @@ scene.on('loaded', () => { }) .shape('icon', 'text') .size(20) - .color('w', ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99']) + .color('w', [ '#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99' ]) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [ 40, 0 ], // 文本相对锚点的偏移量 [水平, 垂直] diff --git a/examples/point/text/demo/iconfonts.js b/examples/point/text/demo/iconfonts.js index 6a68dacc95..a4e9fdaf53 100644 --- a/examples/point/text/demo/iconfonts.js +++ b/examples/point/text/demo/iconfonts.js @@ -13,12 +13,12 @@ const scene = new Scene({ }) }); const dataColor = { - bigRainBC: "#285A8C", - middleRainBC: "#326EA0", - smallRainBC: "#4678AA", - sunBC: "#00BFFF", - cloudBC: "#1E90FF" -} + bigRainBC: '#285A8C', + middleRainBC: '#326EA0', + smallRainBC: '#4678AA', + sunBC: '#00BFFF', + cloudBC: '#1E90FF' +}; const originData = [ { lng: 121.7, diff --git a/examples/point/text/demo/temperture.js b/examples/point/text/demo/temperture.js index 4bf45f9a84..3ed1326a1d 100644 --- a/examples/point/text/demo/temperture.js +++ b/examples/point/text/demo/temperture.js @@ -43,7 +43,7 @@ scene.on('loaded', () => { }) .source(data) .shape('fill') - .color('count', ['#f2f0f7','#dadaeb','#bcbddc','#9e9ac8','#756bb1','#54278f']) + .color('count', [ '#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f' ]) .style({ opacity: 0.6 }); diff --git a/examples/point/text/demo/updown.js b/examples/point/text/demo/updown.js index 33fd94432d..26578e8d81 100644 --- a/examples/point/text/demo/updown.js +++ b/examples/point/text/demo/updown.js @@ -30,7 +30,7 @@ scene.on('loaded', () => { }) .source(data) .shape('fill') - .color('count', ['#f2f0f7','#dadaeb','#bcbddc','#9e9ac8','#756bb1','#54278f']) + .color('count', [ '#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f' ]) .style({ opacity: 0.6 }); diff --git a/packages/component/src/control/BaseControl.ts b/packages/component/src/control/BaseControl.ts index 39e79caeb2..378c583d5c 100644 --- a/packages/component/src/control/BaseControl.ts +++ b/packages/component/src/control/BaseControl.ts @@ -45,7 +45,6 @@ export default class Control extends EventEmitter { }; } public setPosition(position: PositionName = 'bottomright') { - // 考虑组件的自动布局,需要销毁重建 const controlService = this.controlService; if (controlService) { diff --git a/stories/Map/components/amap2demo_text.tsx b/stories/Map/components/amap2demo_text.tsx index 3061d29f6c..7896a1122b 100644 --- a/stories/Map/components/amap2demo_text.tsx +++ b/stories/Map/components/amap2demo_text.tsx @@ -86,58 +86,9 @@ export default class Amap2demo_text extends React.Component { // textAllowOverlap: true, }); scene.addLayer(pointLayer); + }); - // https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json - // const pointIconFontLayer = new PointLayer({}) - // .source( - // [ - // { - // j: 140, - // w: 30, - // m: '', - // }, - // { - // j: 140, - // w: 32, - // m: '', - // }, - // { - // j: 140, - // w: 34, - // m: 'icon1', - // }, - // { - // j: 140, - // w: 36, - // m: 'icon2', - // }, - // ], - // { - // parser: { - // type: 'json', - // x: 'j', - // y: 'w', - // }, - // }, - // ) - // .shape('m', 'text') - // .size(12) - // .color('w', ['#f00', '#f00', '#0f0']) - // .style({ - // textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - // textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] - // spacing: 2, // 字符间距 - // padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - // stroke: '#ffffff', // 描边颜色 - // strokeWidth: 0.3, // 描边宽度 - // strokeOpacity: 1.0, - // fontFamily, - // // fontFamily: "Times New Roman", - // iconfont: true, - // textAllowOverlap: true, - // }); - // scene.addLayer(pointIconFontLayer); fetch( 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', diff --git a/stories/Map/components/amap2demo_textSelect.tsx b/stories/Map/components/amap2demo_textSelect.tsx new file mode 100644 index 0000000000..0211f38edc --- /dev/null +++ b/stories/Map/components/amap2demo_textSelect.tsx @@ -0,0 +1,126 @@ +// @ts-ignore +import { ILngLat, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; +export default class Amap2demo_textSelect extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + let fontFamily = 'iconfont'; + let fontPath = + '//at.alicdn.com/t/font_2534097_99x8u6zpili.woff2?t=1621842922496'; + + + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30.258134], + pitch: 0, + style: 'light', + zoom: 3, + // viewMode: "3D", + // mask + }), + }); + this.scene = scene; + scene.addIconFont('icon1', ''); + // scene.addIconFont("icon2", "") + + // scene.addIconFonts([ + // ['icon1', ''], + // ['icon2', ''], + // ]); + + scene.addFontFace(fontFamily, fontPath); + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json', + ) + .then((res) => res.json()) + .then((data) => { + console.log(data.list[0]) + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('icon', 'text') + .size(12) + .color('w', ['#f00', '#f00', '#0f0']) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [-10, 0], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + fontFamily, + // fontFamily: "Times New Roman", + iconfont: true, + // textAllowOverlap: true, + }); + scene.addLayer(pointLayer); + pointLayer.boxSelect([0, 0, 155, 278], (f) => { + console.log('======') + console.log(f) + }) + }); + + + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json', + ) + .then((res) => res.json()) + .then((data) => { + const pointLayer = new PointLayer({}) + .source(data.list, { + parser: { + type: 'json', + x: 'j', + y: 'w', + }, + }) + .shape('m', 'text') + .size(12) + .color('w', ['#0e0030', '#0e0030', '#0e0030']) + .style({ + textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left + textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] + spacing: 2, // 字符间距 + padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + strokeWidth: 0.3, // 描边宽度 + strokeOpacity: 1.0, + // textAllowOverlap: true + }); + scene.addLayer(pointLayer); + }); + }); + } + + public render() { + return ( + <> +
+ + ); + } +} diff --git a/stories/Map/map.stories.tsx b/stories/Map/map.stories.tsx index 22f5347bf0..f4208354e2 100644 --- a/stories/Map/map.stories.tsx +++ b/stories/Map/map.stories.tsx @@ -5,6 +5,7 @@ import Amap2demo from './components/amap2demo' import Amap2demo_extrude from './components/amap2demo_extrude' import Amapdemo_extrude from './components/amapdemo_extrude' import Amap2demo_text from './components/amap2demo_text' +import Amap2demo_textSelect from './components/amap2demo_textSelect' import Amap2demo_iconfont from './components/amap2demo_iconfont'; import Amap2demo_image from './components/amap2demo_image' @@ -54,6 +55,7 @@ storiesOf('地图方法', module) .add('高德地图 point/extrude', () => ) .add('高德地图2.0 point/extrude', () => ) .add('高德地图2.0 point/text', () => ) + .add('高德地图2.0 point/textSelect', () => ) .add('高德地图2.0 point/iconfont', () => ) .add('高德地图2.0 point/image', () => )