mirror of https://gitee.com/antv-l7/antv-l7
feat(many): gaode1.x -> gaode2.0 not finished
This commit is contained in:
parent
bee72723d4
commit
0fdb6d1b0d
|
@ -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. 偏移经纬度,用于解决高精度抖动问题
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -30,8 +30,10 @@ export interface IMapWrapper {
|
|||
}
|
||||
|
||||
export interface IMapService<RawMap = {}> {
|
||||
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<RawMap = {}> {
|
|||
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];
|
||||
}
|
||||
|
|
|
@ -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<void>((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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:脏检查,决定是否需要渲染
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new PointModels[modelType](this);
|
||||
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
|
|
|
@ -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(),
|
||||
}),
|
||||
];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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<AMap.Map & IAMapInstance> {
|
||||
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<void>((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(
|
||||
|
|
|
@ -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<IMapCamera>) {
|
||||
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];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.amap-logo{
|
||||
display: none !important;
|
||||
}
|
|
@ -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<AMap.Map & IAMapInstance> {
|
||||
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<IMapConfig>;
|
||||
|
||||
@inject(TYPES.ICoordinateSystemService)
|
||||
private readonly coordinateSystemService: ICoordinateSystemService;
|
||||
|
||||
@inject(TYPES.IEventEmitter)
|
||||
private eventEmitter: any;
|
||||
|
||||
private markerContainer: HTMLElement;
|
||||
private $mapContainer: HTMLElement | null;
|
||||
|
||||
private viewport: Viewport;
|
||||
|
||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
||||
|
||||
/**
|
||||
* 设置数据的绘制中心 高德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<[number, number]>): Array<Array<[number, number]>>|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<IStatusOptions>): void {
|
||||
this.map.setStatus(option);
|
||||
}
|
||||
public pixelToLngLat(pixel: [number, number]): ILngLat {
|
||||
const lngLat = this.map.pixelToLngLat(new AMap.Pixel(pixel[0], pixel[1]));
|
||||
return { lng: lngLat.getLng(), lat: lngLat.getLat() };
|
||||
}
|
||||
public lngLatToPixel(lnglat: [number, number]): IPoint {
|
||||
const p = this.map.lnglatToPixel(new AMap.LngLat(lnglat[0], lnglat[1]));
|
||||
return {
|
||||
x: p.getX(),
|
||||
y: p.getY(),
|
||||
};
|
||||
}
|
||||
public containerToLngLat(pixel: [number, number]): ILngLat {
|
||||
const ll = new AMap.Pixel(pixel[0], pixel[1]);
|
||||
const lngLat = this.map.containerToLngLat(ll);
|
||||
return {
|
||||
lng: lngLat?.getLng(),
|
||||
lat: lngLat?.getLat(),
|
||||
};
|
||||
}
|
||||
public lngLatToContainer(lnglat: [number, number]): IPoint {
|
||||
const ll = new AMap.LngLat(lnglat[0], lnglat[1]);
|
||||
const pixel = this.map.lngLatToContainer(ll);
|
||||
return {
|
||||
x: pixel.getX(),
|
||||
y: pixel.getY(),
|
||||
};
|
||||
}
|
||||
|
||||
public 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<void> {
|
||||
const {
|
||||
id,
|
||||
style = 'light',
|
||||
minZoom = 0,
|
||||
maxZoom = 18,
|
||||
token = AMAP_API_KEY,
|
||||
mapInstance,
|
||||
plugin = [],
|
||||
...rest
|
||||
} = this.config;
|
||||
// 高德地图创建独立的container;
|
||||
|
||||
// tslint:disable-next-line:typedef
|
||||
await new Promise<void>((resolve) => {
|
||||
const resolveMap = () => {
|
||||
if (mapInstance) {
|
||||
this.map = mapInstance as AMap.Map & IAMapInstance;
|
||||
this.$mapContainer = this.map.getContainer();
|
||||
|
||||
setTimeout(() => {
|
||||
this.map.on('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;
|
||||
}
|
||||
}
|
|
@ -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',
|
||||
};
|
|
@ -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 };
|
||||
|
|
|
@ -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<Map> {
|
||||
public version: string = Version.L7MAP;
|
||||
public map: Map;
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
|
|
|
@ -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<Map & IMapboxInstance> {
|
||||
public version: string = Version.MAPBOX;
|
||||
public map: Map & IMapboxInstance;
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* 当前 L7 内部存在的地图版本
|
||||
*/
|
||||
export enum Version {
|
||||
'GAODE1.x' = 'GAODE1.x',
|
||||
'GAODE2.x' = 'GAODE2.x',
|
||||
'MAPBOX' = 'MAPBOX',
|
||||
'L7MAP' = 'L7MAP',
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
{/* <div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '0px',
|
||||
|
@ -115,8 +125,8 @@ export default class GaodeMapComponent extends React.Component {
|
|||
height: '200px',
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
/> */}
|
||||
{/* <div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '0px',
|
||||
|
@ -135,7 +145,7 @@ export default class GaodeMapComponent extends React.Component {
|
|||
height: '100%',
|
||||
width: '800px',
|
||||
}}
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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('地图中心点', () => <MapCenter />);
|
||||
storiesOf('地图方法', module)
|
||||
.add('高德地图 point/demo', () => <MapCenter />)
|
||||
.add('高德地图2.0 point/demo', () => <Amap2demo />)
|
||||
.add('高德地图 point/extrude', () => <Amapdemo_extrude />)
|
||||
.add('高德地图2.0 point/extrude', () => <Amap2demo_extrude />)
|
||||
.add('高德地图2.0 point/text', () => <Amap2demo_text />)
|
||||
.add('高德地图2.0 point/image', () => <Amap2demo_image />)
|
||||
.add('高德地图2.0 polygon', () => <Amap2demo_polygon />)
|
||||
.add('高德地图2.0 polygon_extrude', () => <Amap2demo_polygon_extrude />)
|
||||
.add('高德地图2.0 line_arc', () => <Amap2demo_arcLine />)
|
||||
|
|
Loading…
Reference in New Issue