Atlas-SDK介绍

Atlas-SDK主要由地图Map、图层Layer、数据源Source、弹窗Overlay、元素绘制Edit几个对象组成。本文主要介绍如何快速使用SDK开发包中的主要功能。

入门完整示例

一个完整的简单入门实例包含以下几个核心步骤:

  1. (可选)获取Atlas控制台令牌,令牌获取请参见开发者令牌管理

  2. 创建一个地图实例。

  3. 创建图层需要的数据实例。

    说明

    可通过连接Atlas服务的数据源。

  4. 创建待绘制的图层实例。

  5. 将图层添加到地图实例展示。

  6. (可选)添加弹窗元素,进行交互设置。

  7. (可选)添加绘制元素,进行自定义绘制。

<script>
import {
  AtlasMap,
  AtlasVectorSource,
  CircleLayer,
  Popup,
  Edit,
  RasterLayer,
  RasterSource,
  setCredentials,
} from '@datav-atlas/map';

/** 设置Atlas信任令牌 */
setCredentials({
  apiBaseUrl: 'https://atlas.datav.aliyun.com/',  
  token: '你的token',  // 获取说明参见下一节【连接Atlas服务】。
});

export default {
  name: 'App',
  components: {
  },
  mounted() {
    /** 创建地图实例 */
    const map = new AtlasMap('container', {
      crs: 'EPSG:3857',
      center: [119.87512573588158, 30.06950277327222],
      zoom: 8,
      pitch: 0,
      rotate: 0,
    });

    /** 创建栅格图层 */
    const baseMap = new RasterLayer({
      id: 'base',
      source: new RasterSource({
        id: 'base',
        data: 'https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
        maxzoom: 18,
        tileSize: 256,
      }),
      order: 0,
    });

     /** 使用Atlas控制台的数据源 */
    const pointSource = new AtlasVectorSource({
      id: 'point',
      data: {
        connectionId: '数据连接ID',  // 获取说明参见下一节【连接Atlas服务】。
        sql: '你的SQL',
      },
    });

     /** 创建基础点图层 */
    const pointLayer = new CircleLayer({
      id: 'pointLayer',
      source: pointSource,
      order: 10,
      style: {
        color: 'orange',
        radius: 4,
        opacity: 0.8,
        strokeColor: 'white',
        strokeWidth: 1,
      },
    });
    /** 将图层添加到地图实例中 */
    baseMap.addTo(map);
    pointLayer.addTo(map);
  }
}
</script>
<template>
  <div id="container" style="width: 800px;height: 600px"></div>
</template>

连接Atlas服务

令牌授权创建无水印版地图

令牌获取请参见开发者令牌管理。未设置Token时,地图会添加水印,但代码正常使用。

import {
  setCredentials,
} from '@datav-atlas/map';

setCredentials({
  apiBaseUrl: 'https://atlas.datav.aliyun.com/',
  token: 'atlas中复制的token',
});

使用Atlas数据源

connectionIdsql语句获取请参见开发者令牌管理

import {
  AtlasVectorSource,
  CircleLayer
} from '@datav-atlas/map';

const pointSource = new AtlasVectorSource({
  id: 'point',
  data: {
    connectionId: '要使用的数据的数据连接ID',
    sql: '数据表查询sql语句,例如,'SELECT "gid", "geom", "count", "name", "avgprice" FROM "public"."hangzhou_house_sample";'',
  },
});

const pointLayer = new CircleLayer({
  id: 'pointLayer',
  source: pointSource,
  order: 10,
  style: {
    color: 'orange',
    radius: 4,
    opacity: 0.8,
    strokeColor: 'white',
    strokeWidth: 1,
  },
});

地图实例

地图配置项和创建地图示例如下:

const mapOptions:MapOptions= {
  crs: 'EPSG:3857',
  center: [119.87512573588158, 30.06950277327222],
  zoom: 8,
  pitch: 0,
  rotate: 0,
};

const map = new AtlasMap('container', mapOptions);

相关接口定义如下:

export interface IAnimationParams {
  /** 动画持续时间/ms */
  duration?: number;
  /** 动画启动延迟/ms */
  delay?: number;
  /** 时间函数 */
  ease?: keyof typeof EASE | ((t: number) => number);
}

// 缓动函数参考: https://github.com/d3/d3-ease
const EASE = {
  easeBounce,
  easeBounceIn,
  easeBounceInOut,
  easeBounceOut,
  easeCircle,
  easeCircleIn,
  easeCircleInOut,
  easeCircleOut,
  easeCubic,
  easeCubicIn,
  easeCubicInOut,
  easeCubicOut,
  easeExp,
  easeExpIn,
  easeExpInOut,
  easeExpOut,
  easeLinear,
  easeQuad,
  easeQuadIn,
  easeQuadInOut,
  easeQuadOut,
  easeSin,
  easeSinIn,
  easeSinInOut,
  easeSinOut,
  easeElastic: easeElastic.amplitude(1).period(0.3),
  easeElasticIn: easeElasticIn.amplitude(1).period(0.3),
  easeElasticInOut: easeElasticInOut.amplitude(1).period(0.3),
  easeElasticOut: easeElasticOut.amplitude(1).period(0.3),
};

interface IMapOptions {
  /** 中心点 */
  center?:Array<number>;
  /** 缩放等级 */
  zoom?:number;
  /** 倾斜角度 */
  pitch?:number;
  /** 旋转角度 */
  rotate?:number;
  /** 项目token,用于去除水印 */
  token?: string;
  /** 投影坐标系 */
  projection?:string | Projection;
  /** 投影坐标系 */
  crs?: string;
  /** 静态资源地址 */
  staticBaseUrl?: string;
  /** 渲染过渡动画参数 */
  transition?: ITransitionParams & { animation?: boolean };
  /** 启用高性能渲染(影响流畅度) */
  highPerformance?:boolean;
  /** 显示瓦片边界 */
  showTileBoundaries?:boolean;
  /** 允许跨数据源碰撞检测 */
  crossSourceCollisions?:boolean;
  /** 最小缩放等级 */
  minzoom?: number;
  /** 最大缩放等级 */
  maxzoom?: number;
  /** 是否开启webgl2 */
  webgl2?: boolean;
  /** 自动调整大小 */
  autoResize?:boolean;
  /** 允许拖拽 */
  panEnable?: boolean;
  /** 允许缩放 */
  zoomEnable?: boolean;
  /** 允许旋转 */
  rotateEnable?: boolean;
  /** 保留canvas渲染buffer */
  preserveDrawingBuffer?: boolean;
  /** 开启抗锯齿 */
  antialias?:boolean;
}

地图能力设置

/** 允许拖拽地图 */
enablePan(value: boolean): void;
/** 允许旋转地图 */
enableRotate(value: boolean): void;
/** 允许缩放地图 */
enableZoom(value: boolean): void;
/** 允许键盘事件 */
enableKeyboard(value: boolean): void;
/** 允许使用后期效果 */
enableEffect(value: boolean): void;

地图配置项设置

/** 更改地图投影 */
setProjection(project: string): void;
/** 更改过度动画配置 */
setTransition(options: ITransitionParams & { animation?: boolean }): void;
/** 触摸板缩放速度, 默认值为 1/100, 值越大缩放速度越快 */
setZoomRate(zoomRate: number): void;
/** 鼠标滚轮板缩放速度, 默认值为 1/900, 值越大缩放速度越快 */
setWheelZoomRate(wheelZoomRate: number): void;

图层管理

/** 添加图层 */
addLayer(layer: Layer): void
/** 获取图层 */
getLayer(id: string): Layer
/** 移除图层 */
removeLayer(id: string): void

数据源管理

/** 添加数据源 */
addSource<T extends ISourceType>(source: Source<T>): IGISourceClass[T]
/** 获取数据源 */
getSource(id: string): Source
/** 移除数据源 */
removeSource(source: string | Source<ISourceType>): void;

地图视角设置

/** 缩放至指定范围 */
easeTo(options: IFlyToOptions): void;
/** 飞至指定范围 */
flyTo(options: IFlyToOptions): void;
/** 缩放至指定矩形范围 */
fitBounds(
  bounds: [number, number, number, number],
  options?: IFitBoundsOptions,
): void;
/** 缩放至指定图层 */
fitToLayer(layerIds: string | string[], options?: IFitBoundsOptions): void;

相关接口定义如下:

interface IViewOptions {
    center?: [number, number];
    zoom?: number;
    rotate?: number;
    pitch?: number;
}
interface IFlyOptions {
    /** 最小缩放层级 */
    minZoom?: number;
    /** 动画速度 */
    speed?: number;
    /** 动画轨迹曲率 */
    curve?: number;
    /** 过渡时间 */
    duration?: number;
    /** 最大过渡时间 */
    maxDuration?: number;
    /** 屏幕速度 */
    screenSpeed?: number;
    /** 相机偏移(像素) */
    offset?: [number, number];
}
type IFlyToOptions = IFlyOptions & IViewOptions;
type IFitBoundsOptions = IFlyOptions & {
    /** 缩放后边距 */
    padding?: {
        top: number;
        bottom: number;
        right: number;
        left: number;
    } | number;
    /** 最大缩放层级 */
    maxZoom?: number;
};

生命周期管理

/** 手动触发重绘 */
repaint(): void;
/** 销毁实例 */
destroy(): void;

事件交互

/** 地图加载完成 */
map.on('load',(e)=> { /** 响应事件 */ })
/** 地图销毁 */
map.on('destory',()=> { /** 响应事件 */ })
/** 地图渲染前 */
map.on('beforeRender',()=> { /** 响应事件 */ })
/** 地图是否空闲 */
map.on('workerIdle',()=> { /** 响应事件 */ })
/** 地图移动时 */
map.on('move',()=> { /** 响应事件 */ })
/** 地图移动结束 */
map.on('moveEnd',()=> { /** 响应事件 */ })
/** 地图缩放时 */
map.on('resize',()=> { /** 响应事件 */ })
/** 地图被点击时 */
map.on('click',()=> { /** 响应事件 */ })
/** 地图被双击时 */
map.on('dblclick',()=> { /** 响应事件 */ })
/** 地图被右键时 */
map.on('contextmenu',()=> { /** 响应事件 */ })
/** 鼠标在地图按下时 */
map.on('mousedown',()=> { /** 响应事件 */ })
/** 鼠标在地图抬起时 */
map.on('mouseup',()=> { /** 响应事件 */ })
/** 鼠标在地图移动时 */
map.on('mousemove',()=> { /** 响应事件 */ })

数据源

CsvSource

 const source = new CsvSource({
  id: 'test',
  data: 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json',
  vector: false,
});

GeoJsonSource

 const source = new GeoJsonSource({
  id: 'test',
  data: 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json',
  vector: false,
});

RasterSource

const source = new RasterSource({
  id: 'base',
  data: 'https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
  maxzoom: 18,
  tileSize: 256,
});

地图图层

Atlas SDK支持创建多种地图图层,图层创建参数如下,不同类型图层的样式参数存在差异:

interface IPrimitiveParams<T extends IStyle = IStyle> {
  /** ID */
  id: string;
  /** 数据源对象 */
  source?: Source<ISourceType>;
  /** 可视缩放范围 */
  minzoom?: number;
  maxzoom?: number;
  /** 图层样式 */
  style?: T;
  /** 过滤表达式 */
  filter?: IExpression;
  /** 图层顺序 */
  order?: number;
  /** 交互支持 */
  interaction?: Partial<IInteraction>;
  /** 后期效果 */
  effect?: IPassOptions<any>[] | string;
}

创建的图层实例支持以下方法:

/** 添加到地图 */
addTo(map: AtlasMap): void;
/** 删除图层 */
remove(): void;
/** 设置缩放范围 */
setZoomRange(minzoom: number, maxzoom: number): void;
/** 设置图层顺序 */
setOrder(order: number): void;
/** 设置图层交互 */
setInteraction(interaction: Partial<IInteraction>): void;
/** 设置图层过滤表达式 */
setFilter(filter: IExpression): void;
/** 设置图层样式 */
setStyle(style: T): void;
/** 设置图层后期效果 */
setEffect<T extends IEffectTypes>(effect?: IPassOptions<T>[] | string): void;
/** 设置数据源 */
setSource(source: Source<ISourceType>): void;

1、基础点图层 CircleLayer

基础点图层渲染圆形点,用于大规模点渲染;

const pointLayerParams: IPrimitiveParams<ICircleStyle> = {
  id: 'pointLayer',
  source: pointSource,
  order: 10,
  style: {
    color: 'orange',
    radius: 4,
    opacity: 0.8,
    strokeColor: 'white',
    strokeWidth: 1,
  },
};

const pointLayer = new CircleLayer(pointLayerParams);

相关接口定义如下:

type ICircleStyle = IStyle & Partial<{
  /** 颜色 */
  color: string | IExpression;
  /** 点半径 */
  radius: number | IExpression;
  /** 模糊半径 */
  blur: number | IExpression;
  /** 透明度 */
  opacity: number | IExpression;
  /** 半径单位:像素/米 */
  units: 'pixels' | 'meters';
  /** 边框颜色 */
  strokeColor: string | IExpression;
  /** 边框宽度 */
  strokeWidth: number | IExpression;
  /** 边框透明度 */
  strokeOpacity: number | IExpression;
  /** 地图倾斜时的锚点 */
  pitchAlignment: 'viewport' | 'map';
  /** 排序字段 */
  sortKey: string | null;
  /** 优先显示要素ID */
  priorityIds: Array<string> | null;
}>;

2、图标点图层 SymbolLayer

const symbolLayerParams: IPrimitiveParams<ISymbolStyle> = {
  id: 'symbolLayer',
  source: symbolSource,
  order: 1,
  style: {
    iconImage:'https://img.alicdn.com/imgextra/i4/O1CN01gb3kT81vg6mY9YD4b_!!6000000006201-2-tps-64-64.png',
    iconSize:0.5,
    iconAllowOverlap:true
  },
};

const symbolLayer = new SymbolLayer(symbolLayerParams);

相关接口定义如下:

type IAlignment = 'map' | 'viewport' | 'auto';
type ISymbolStyle = IStyle &
  Partial<{
    /** 排序字段 */
    sortKey: string | null;
    /** 优先显示要素ID */
    priorityIds: Array<string> | null;
    /** 是否允许覆盖,默认false */
    iconAllowOverlap: boolean;
    /** 图标锚点; 默认值:"center", 可选值:"left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right", */
    iconAnchor:
      | 'center'
      | 'left'
      | 'right'
      | 'top'
      | 'bottom'
      | 'top-left'
      | 'top-right'
      | 'bottom-left'
      | 'bottom-right'
      | IExpression;
    /** 图标颜色;只支持SDF图标; */
    iconColor: string | IExpression;
    /** 图标描边模糊度;单位像素 */
    iconHaloBlur: number | IExpression;
    /** 图标描边颜色 */
    iconHaloColor: string | IExpression;
    /** 图标描边宽度;单位像素 */
    iconHaloWidth: number | IExpression;
    /** 如果设置true,其他图标与该图标发生碰撞时依然会显示 */
    iconIgnorePlacement: boolean;
    /** 图标图片 */
    iconImage: string | IExpression;
    /** 果设置true,图标会自动进行翻转,防止图标渲染颠倒,需要icon-rotation-alignment为'map',symbol-placement为'line'、'line-center' */
    iconKeepUpright: boolean;
    /** 图标偏移,像素,正值右下,负值左上,跟随icon-rotate旋转方向变化 */
    iconOffset: [number, number] | IExpression;
    /** 图标透明度 */
    iconOpacity: number | IExpression;
    /** 如果为true,当图标与其他符号碰撞而文本没有碰撞时,文本将不显示 */
    iconOptional: boolean;
    /** 图标边距,大于或等于0,单位像素 */
    iconPadding: number;
    /** 倾斜地图时图标的方向 */
    iconPitchAlignment: IAlignment;
    /** 图标旋转,单位度 */
    iconRotate: number | IExpression;
    /** 旋转地图时图标方向;可选值"map", "viewport", "auto"
     * "map":当符号放置方式为点,图标将对其地图东西方向,当放置方式为line或者line-center, 将图标x轴与线对齐
     * "viewport": 忽略符号放置方式,符号X轴与视窗口X轴对齐
     * "auto": 当符号放置方式为'point',相当于'viewport',当放置方式为'line'、'line-center',相当于是'map'
     */
    iconRotationAlignment: IAlignment;
    /** 图标尺寸,默认放大比例,1为图标原始尺寸渲染效果 */
    iconSize: number | IExpression;
    /** 尺寸单位;可选值: "scales","pixels","meters"
     * 'scales':放大比例
     * 'pixels':像素
     * 'meters':米
     */
    iconSizeUnits: 'scales' | 'pixels' | 'meters';
    /** 动图播放持续时间,单位ms */
    iconAnimationDuration: number | IExpression;
    /** 动图播放延迟,支持表达式 */
    iconAnimationDelay: number | IExpression;
    /** 图标缩放,适应文本尺寸, 可选值"none", "width", "height", "both"
     * 'none':图标按照默认长宽比展示
     * 'width': 图标在x轴方向适应文本尺寸
     * 'height': 图标在y轴方向适应文本尺寸
     * 'both': 图标在x轴,y轴都适应文本尺寸
     */
    iconTextFit: 'none' | 'width' | 'height' | 'both';
    /** 根据文本尺寸决定的图标边距, 顺序为上右下左,需要iconTextFit设置'width'、'height'、'both' */
    iconTextFitPadding: [number, number, number, number];
    /** 移动文本锚点; 图标锚点相对于其位置平移的距离,正值表示右下,负值表示左上 */
    iconTranslate: [number, number];
    /** 控制图标平移的参照系; 可选值:'map'、'viewport' */
    iconTranslateAnchor: 'map' | 'viewport';
    /** 当为true,符号将不会跨越瓦片边缘以避免相互冲突。开启全局避让后不需要启用该属性 */
    symbolAvoidEdges: boolean;
    /** 符号相对于几何信息的防止方式,可选值:"point", "line", "line-center", "line-start", "line-end"
     * 'point': 图标放置在几何图形所在的位置,对 LineString 放置于第一个顶点
     * 'point-end': 图标放置在几何图形所在的位置,对于 LineString 放置于最后一个顶点
     * 'line': 标签沿几何图形的线放置。只能用于 LineString 和 Polygon 几何图形
     * 'line-center': 标签放置在几何图形线的中心。只能用于 LineString 和 Polygon 几何图形。注意,矢量切片中的单个要素可能包含多个线几何图形
     */
    symbolPlacement:
      | 'point'
      | 'line'
      | 'line-center'
      | 'line-start'
      | 'line-end'
      | 'line-start-point'
      | 'line-end-point';
    /** 要素会更根据该属性对应的值进行由小到大的排序渲染,当iconAllowOverlap 和 textAllowOverlap等于false,值小的优先渲染,值大后渲染。当iconAllowOverlap 和 textAllowOverlap等于true,发生碰撞时值大的会优先渲染选择权 */
    symbolSortKey: string;
    /** 要素优先渲染的id集合,在集合里面的要素会渲染置顶 */
    symbolPriorityIds: string[];
    /** 两个符号之间的间距,需要symbolPlacement 为'line' */
    symbolSpacing: number;
    /** 暂未实现 确定同一图层中的符号是按照他们在数据中默认的顺序还是按照他们相对于视窗口y的位置进行渲染,如果需要控制数据的渲染顺序,请使用symbolSortKey
     * 'auto':如果设置symbolSortKey,则按符号排序键对符号进行排序。否则,如果 icon-allow-overlap 或 text-allow-overlap 设置为 true 或 icon-ignore-placement 或 text-ignore-placement 为 false,则按符号相对于视口的 y 位置对符号进行排序
     * 'viewport-y':如果 icon-allow-overlap 或 text-allow-overlap 设置为 true 或 icon-ignore-placement 或 text-ignore-placement 为 false,则按符号相对于视口的 y 位置对符号进行排序
     * 'source':如果设置symbolSortKey,则按符号排序键对符号进行排序。否则,不应用排序;符号以与源数据相同的顺序呈现
     */
    symbolZOrder: 'auto' | 'viewport-y' | 'source';
    /** 是否文字允许覆盖,默认false */
    textAllowOverlap: boolean;
    /** 文字锚点,可选值:"center", "left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right" */
    textAnchor:
      | 'center'
      | 'left'
      | 'right'
      | 'top'
      | 'bottom'
      | 'top-left'
      | 'top-right'
      | 'bottom-left'
      | 'bottom-right'
      | IExpression;
    /** 文字颜色 */
    textColor: string | IExpression;
    /** 文字标签字段或者值 */
    textField: any;
    /** 字体 */
    textFont: string | string[] | IExpression;
    /** 文本描边模糊度 */
    textHaloBlur: number | IExpression;
    /** 文本描边颜色 */
    textHaloColor: string | IExpression;
    /** 文本描边宽度 */
    textHaloWidth: number | IExpression;
    /** 如果设置true,其他图标与该图标发生碰撞时依然会显示 */
    textIgnorePlacement: boolean;
    /** 文本水平对齐,可选值:"auto", "left", "center", "right" */
    textJustify: 'auto' | 'center' | 'left' | 'right' | IExpression;
    /** 如果设置true,图标会自动进行翻转,防止图标渲染颠倒,需要icon-rotation-alignment为'map',symbol-placement为'line'、'line-center' */
    textKeepUpright: boolean;
    /** 文本字符之间间距;单位ems */
    textLetterSpacing: number | IExpression;
    /** 文本行高;单位ems */
    textLineHeight: number | IExpression;
    /** 文字最大旋转角度, 需要symbolPlacement为line或者line-center */
    textMaxAngle: number;
    /** 文本最大宽度;单位:ems;需要symbolPlacement为point */
    textMaxWidth: number | IExpression;
    /** 单位:ems;文本与其锚点的偏移距离。正值表示向右和向下,而负值表示向左和向上。如果与 text-variable-anchor 一起使用,输入值将被视为绝对值。沿 x 轴和 y 轴的偏移量将根据锚点位置自动应用 */
    textOffset: [number, number];
    /** 文本不透明度 */
    textOpacity: number | IExpression;
    /** 如果为true,当文字与其他符号发生冲突而图标不会时,图标不会显示文本 */
    textOptional: boolean;
    /** 文本边距;单位像素;用于检测符号冲突的文本边界框周围的附加区域的大小 */
    textPadding: number;
    /** 倾斜地图时文本的方向
     * 'map': 与地图平面对齐
     * 'viewport': 与视窗平面对齐
     * 'auto':根据textRotationAlignment自动匹配
     */
    textPitchAlignment: IAlignment;
    /** 在符号的锚点方向上文本径向偏移;单位:ems;与textVariableAnchor结合使用非常有用 */
    textRadialOffset: number | IExpression;
    /** 文本旋转角度 */
    textRotate: number | IExpression;
    /** 结合symbolPlacement, 确定文本的旋转行为
     * 'map':当symbolPlacement为point时,文本与地图东西对齐;当symbolPlacement为line或者line-center,将文本x轴与线对齐
     * 'viewport': 文本X轴与视窗对齐,无论symbolPlacement的值如何
     * 'auto':当symbolPlacement为point,相当于viewport; 当symbolPlacement为line或者line-center,相当于map
     */
    textRotationAlignment: IAlignment;
    /** 文本尺寸;单位:像素 */
    textSize: number | IExpression;
    /**
     * 'scales':放大比例
     * 'pixels':像素
     * 'meters':米
     */
    textSizeUnits: 'pixels' | 'scales' | 'meters';
    /** 文本转换;可选值:"none", "uppercase", "lowercase" */
    textTransform: 'uppercase' | 'lowercase' | 'none';
    /** 移动文本锚点; 文本的锚点从其原始位置移动的距离。正值表示右下,负值表示左上 */
    textTranslate: [number, number];
    /** 控制textTranslate的参照系;可选值:'map'、'viewport'
     * map:相对于地图平面
     * viewport: 相对于视窗平移
     */
    textTranslateAnchor: 'map' | 'viewport';
    /** 需要symbolPlacement配置为point,可选值:"center", "left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right"
     * 为了增加在地图上放置高优先级标签的机会,可以提供一组文本锚点位置;textJustify:auto; 会根据锚点位置选择对齐方式,偏移采用textRadialOffset或者textOffset
     */
    textVariableAnchor:
      | 'center'
      | 'left'
      | 'right'
      | 'top'
      | 'bottom'
      | 'top-left'
      | 'top-right'
      | 'bottom-left'
      | 'bottom-right'
      | null;
    /** 可选值:"horizontal", "vertical"
     * 'horizontal':如果文本支持横向排列,则符号将横向排列
     * 'vertical':如果文本支持垂直排列,则符号将垂直排列
     */
    textWritingMode:
      | Array<'horizontal' | 'vertical'>
      | 'horizontal'
      | 'vertical'
      | null;
    height: number | IExpression;
  }>;

3、基础线图层 LineLayer

const lineLayerParams: IPrimitiveParams<ILineStyle> = {
  id: 'lineLayer',
  source: lineSource,
  order: 1,
  style: {
    color:'#E7A99C',
    width:4,
    dasharray:[2,1]
  },
};

const lineLayer = new LineLayer(lineLayerParams);

相关接口定义如下:

type ILineStyle = IStyle &
  Partial<{
    /** 颜色 */
    color: string | IExpression;
    /** 透明度 */
    opacity: number | IExpression;
    /** 模糊半径 */
    blur: number | IExpression;
    /** 线头样式 */
    cap: 'butt' | 'round' | 'square';
    /** 虚线配置 */
    dasharray: Array<number> | null;
    /** 宽度单位 */
    widthUnits: 'pixels' | 'meters';
    /** 转折点样式 */
    join: 'bevel' | 'round' | 'miter';
    /** 贴图 */
    pattern: IExpression | null;
    /** 贴图间隔 */
    patternSpacing: number;
    /** 贴图缩放 */
    patternScale: number | IExpression;
    /** 贴图颜色(用于SDF贴图) */
    patternColor: string | IExpression;
    /** 贴图阴影模糊(用于SDF贴图 */
    patternHaloBlur: number | IExpression;
    /** 贴图阴影颜色(用于SDF贴图 */
    patternHaloColor: string | IExpression;
    /** 贴图阴影宽度(用于SDF贴图 */
    patternHaloWidth: number | IExpression;
    /** 线宽度 */
    width: number | IExpression;
    /** 排序字段 */
    sortKey: string | null;
    /** 优先显示要素ID */
    priorityIds: Array<string> | null;

    /** 开启动画 */
    animation: boolean;
    /** 动画时长 */
    animationDuration: number; // 毫秒
    /** 动画反向 */
    animationReverse: boolean; // 方向
    /** 动画间隔 */
    animationInterval: number; // 间隔比例
    /** 动画类型,trail为动态方向,flow为流动,适用于纹理线,fadeInOut为淡入淡出 */
    animationType: 'flow' | 'trail' | 'fadeInOut';
  }

4、基础面图层 FillLayer

const lineLayerParams: IPrimitiveParams<IFillStyle> = {
  id: 'fillLayer',
  source: fillSource,
  order: 1,
  style: {
    color:'#D74AFF',
    outlineColor:"#CFFAFF",
    opacity:0.5
  },
};

const fillLayer = new FillLayer(fillLayerParams);

相关接口定义如下:

type IFillStyle = IStyle & Partial<{
  /** 颜色 */
  color: string | IExpression;
  /** 透明度 */
  opacity: number | IExpression;
  /** 贴图 */
  pattern: IExpression | null;
  /** 贴图间隔 */
  patternSpacing: number;
  /** 贴图缩放 */
  patternScale: number | IExpression;
  /** 贴图颜色(用于SDF贴图) */
  patternColor: string | IExpression;
  /** 贴图阴影模糊(用于SDF贴图 */
  patternHaloBlur: number | IExpression;
  /** 贴图阴影颜色(用于SDF贴图 */
  patternHaloColor: string | IExpression;
  /** 贴图阴影宽度(用于SDF贴图 */
  patternHaloWidth: number | IExpression;
  patternMode: 'viewport' | 'map'; // 'map' 'viewport'
  patternResolution: number; // 开启 patternMode 'map'生效
  patternOffset: [number, number]; // 开启 patternMode 'map'生效
  /** 排序字段 */
  sortKey: string | null;
  /** 优先显示要素ID */
  priorityIds: Array<string> | null;
}>

5、拉伸面图层 ExtrusionLayer

const lineLayerParams: IPrimitiveParams<IFillExtrusionStyle> = {
  id: 'extrusionLayer',
  source: extrusionSource,
  order: 1,
  style: {
     base:0,
    height:2000,
    color:'#34A9FF',
    opacity:1
  },
};

const fillLayer = new ExtrusionLayer(extrusionLayerParams);

相关接口定义如下:

type IFillExtrusionStyle = IStyle & Partial<{
  /** 底部高度 */
  base: number | IExpression;
  /** 顶面高度 */
  height: number | IExpression;
  /** 颜色 */
  color: string | IExpression;
  /** 顶面颜色 */
  topColor: string | IExpression;
  /** 侧面颜色 */
  sideColor: string | IExpression;
  /** 透明度 */
  opacity: number | IExpression;
  /** 纹理贴图 */
  pattern: string | IExpression | null;
  /** 顶面纹理贴图 */
  topPattern: string | IExpression | null;
  /** 侧面纹理贴图 */
  sidePattern: string | IExpression | null;
  /** 纹理贴图缩放比例 */
  patternScale: number | IExpression;
  /** 侧面纹理贴图缩放比例 */
  sidePatternScale: number | IExpression;
  /** 顶面纹理贴图缩放比例 */
  topPatternScale: number | IExpression;
  /** 纹理贴图透明度 */
  patternOpacity: number | IExpression;
  /** 侧面纹理贴图透明度 */
  sidePatternOpacity: number | IExpression;
  /** 顶面纹理贴图透明度 */
  topPatternOpacity: number | IExpression;
  /** 纹理贴图模式 */
  patternMode: 'viewport' | 'map';
  /** 纹理贴图分辨率 */
  patternResolution: number; // 开启 patternMode 'map'生效
  /** 纹理贴图偏移 */
  patternOffset: [number, number];
  /** 纹理贴图原点位置 */
  patternOriginPosition: number[] | null | IExpression;
  /** 开启侧面颜色渐变加深 */
  verticalGradient: boolean;
  /** 侧面颜色渐变比例 */
  verticalGradientRatio: number;
}>;

6、飞线图层 ArcLineLayer

const arcLineLayerParams: IPrimitiveParams<IArcLineStyle> = {
  id: 'arcLineLayer',
  source: arcLineSource,
  order: 1,
  style: {
  },
};

const arcLineLayer = new ArcLineLayer(arcLineLayerParams);

相关接口定义如下:

type IArcLineStyle = IStyle &
  Partial<{
    /** 排序字段 */
    sortKey: string | null;
    /** 优先显示要素ID */
    priorityIds: Array<string> | null;
    /** 飞线颜色 允许指定纯色 允许配置表达式 */
    color: string | IExpression;
    /** 飞线透明度 与颜色透明度通道乘算 */
    opacity: number | IExpression;
    /** 飞线宽度 */
    width: number | IExpression;
    /** 飞线长度 单位% */
    lineLength: number | IExpression;
    /** 飞线弧度 */
    theta: number | IExpression;
    /** 虚线样式 */
    dasharray: number[] | IExpression | null;
    /** 飞线分段 分段越多弧线越精细 */
    segment: number;
    /** 飞线线头图标 */
    headerIcon: string | IExpression | null;
    /** 线头图标颜色 */
    headerIconColor: string | IExpression;
    /** 线头图标边框颜色 */
    headerIconHaloColor: string | IExpression;
    /** 线头图标尺寸 */
    headerIconSize: number | IExpression;
    /** 线头图标边框宽度 */
    headerIconHaloWidth: number | IExpression;
    /** 尺寸单位,线宽与图标尺寸同步生效 */
    sizeUnits: 'pixels' | 'meters';
    /** 梭形线 */
    shuttle: boolean;
    /** 开启动画 */
    enableAnimation: boolean;
    /** 飞线动画延迟 */
    animationDelay: number | IExpression;
    /** 单条飞线动画持续时间 */
    animationDuration: number | IExpression;
    /** 两条飞线间隔时间 */
    animationInterval: number | IExpression;
  }>;

7、栅格图层 RasterLayer

const rasterLayerParams: IPrimitiveParams<IRasterStyle> = {
  id: 'rasterLayer',
  source: rasterSource,
  order: 1,
  style: {
  },
};

const rasterLayer = new RasterLayer(rasterLayerParams);

相关接口定义如下:

type IRasterStyle = IStyle &
  Partial<{
    /** 颜色映射 */
    color: keyof typeof presets | IExpression | null;
    /** Gamma校正 */
    gamma: number;
    /** 色相 */
    hueRotate: number;
    /** 亮度最大值 */
    brightnessMin: number;
    /** 亮度最小值 */
    brightnessMax: number;
    /** 灰度 */
    grayScale: number;
    /** 反转 */
    invert: number;
    /** 墨度 */
    sepia: number;
    /** 透明度 */
    opacity: number;
    /** 饱和度 [-1, 1] */
    saturation: number;
    /** 对比度 [-1, 1] */
    contrast: number;
    /** 降采样方式 */
    resampling: 'linear' | 'nearest';
    /** 淡入淡出动画时间 */
    fadeDuration: number;
    /** 蒙版颜色 */
    maskColor: string;
  }>;

图层交互

以基础点图层为例,演示图层交互。

const pointLayer = new CircleLayer({
  id: 'pointLayer',
  source: pointSource,
  order: 10,
  interaction: {
    // 点击交互
    click: true,
    // hover交互
    mousemove: true,
  },
  style: {
    color: 'orange',
    radius: 4,
    opacity: 0.8,
    strokeColor: 'white',
    strokeWidth: 1,
  },
});

// 配置交互事件
pointLayer.on('click', e => { console.log(e) });
pointLayer.on('mousemove', e => { console.log(e) });

pointLayer.off('click', e => { console.log(e) });
pointLayer.off('mousemove', e => { console.log(e) });

事件实例格式

  • type:交互类型;

  • point: 鼠标点击的位置;

  • feature:交互要素,null表示未交互到图层内要素;

  • lngLat:经纬度位置;

  • map:当前地图实例;

  • originEvent:原始DOM事件实例;

image

添加弹窗

示例代码如下:

const pointLayer = new CircleLayer({
  ...
});

const popup = new Popup({
  id: 'test-popup',
  position: 'map',
  closeButton: false,
  closeOnClick: false,
  showTip: true
});

const content = document.createElement('div');
content.style.width = '150px';
content.style.height = '60px';
content.style.display = 'flex';
content.style.justifyContent = 'center';
content.style.alignItems = 'center';

pointLayer.on('click', (e) => {
  if (e.feature) {
    popup.setPos([e.lngLat.x, e.lngLat.y]);
    content.innerText = e.feature.properties.name;
    popup.setDOMContent(content);
    popup.addTo(map);
  } else {
    popup.remove();
  }
});

相关接口定义:

interface IPopupOptions {
  /** 弹窗的唯一标识符 */
  id?: string;
  /** 是否显示关闭按钮 */
  closeButton?: boolean;
  /** 点击地图时关闭弹窗 */
  closeOnClick?: boolean;
  /** 移动地图时关闭弹窗 */
  closeOnMove?: boolean;
  /** 锚点位置 */
  anchor?: IAnchorType;
  /** 标签显示位置:固定于画布 / 跟随地图 */
  position?: 'viewport' | 'map';
  /** 指定每个 anchor 对应的 offset,可以设置为数值/数组/对象 */
  offset?: number | Array<number> | Partial<Record<IAnchorType, number[]>>;
  /** 需要添加到 container 中的 class,空格分隔 */
  className?: string;
  /** 弹窗最大宽度,CSS 的 max-width 属性值 */
  maxWidth?: string;
  /** anchor 边界切换的 padding */
  padding?: number;
  /** 是否显示弹窗角标 */
  showTip?: boolean;
  /** 指针事件设置 */
  pointerEvents?: string;
  /** 边框样式配置 */
  border?: IBorder;
  /** 内容的内边距 */
  contentPadding?: string;
  /** 背景颜色 */
  bgColor?: string;
  /** 弹窗的阴影样式 */
  boxShadow?: string;
  /** 关闭按钮的颜色 */
  closeBtnColor?: string;
}

type IAnchorType = "center" | "top-right" | "bottom-right" | "top-left" | "bottom-left" | "left" | "right" | "top" | "bottom" | "center-left" | "center-right";

interface IBorder{
  radius?: number;
  color?: string;
  width?: number;
  type?: string; 
};

弹窗对象调用方法:

/** 添加到地图 */
addTo(map: AtlasMap): void;
/** 从地图移除 */
remove(): void;
/** 设置弹窗内容 */
setDOMContent(content: HTMLElement): void;
/** 设置弹窗位置,position为map时,设置经纬度,viewport时设置xy像素值 */
setPos(pos: [number, number]): void;
/** 设置锚点 */
setAnchor(anchor: IAnchorType): void;
/** 设置是否显示tip */
setShowTip(showTip: boolean): void;
/** 设置边距 */
setPadding(padding: number): void;
/** 设置是否显示关闭按钮 */
setCloseBtn(enable: boolean): void;

绘制元素

地图绘制功能通过在地图中添加虚拟控件Edit对象开启。

const edit = new Edit({
  id: 'test-edit',
  mode: 'drawCircle',
  modeOption: {...},
  layerStyle: {...},
});
edit.addTo(map);
/** 开启编辑模式 */
edit.setActive(true);

支持的绘制模式包括:

  • drawFill 绘制多边形。

  • drawCircle 绘制圆形。

  • drawLine 绘制线。

  • drawPoint 绘制点。

  • drawRect 绘制矩形。

  • drawRoundRect 绘制圆角矩形。

  • modify 编辑顶点。

  • scaleRotate 缩放 & 旋转。

  • translate 平移。

  • snap 吸附顶点,通常与编辑一起使用,例如:mode: ['snap', 'modify']。

  • measureArea 测量面积。

  • measureDistance 测量长度。

可以通过调用setMode方法切换模式:

setMode(mode: IEditMode, modelOption?: IModeOption): void;

相关接口定义如下:

type IModeOption = Partial<{
  // 修改该属性可以自定义提示内容
  tips: Partial<typeof defaultTips>;
  pixelTolerance: number;
  /** drawCircle */
  circleSeg: number;
  radiusMode: boolean;
  /** drawRect */
  round: boolean;
  roundRatio: number;
  roundSeg: number;
  /** modify */
  canDelete: boolean;
  canInsert: boolean;
  /** modifyScaleRotate */
  rotate: boolean;
  scale: boolean;
  /** snap */
  showVertexPoints: boolean;
  snapToPointer: boolean;
}>;

const defaultTips = {
  drawCircle: ['单击放置首个顶点', '单击完成绘制'],
  drawFill: ['单击放置首个顶点', '单击继续绘制', '双击完成绘制'],
  drawLine: ['单击放置首个顶点', '单击继续绘制', '双击完成绘制'],
  drawPoint: ['单击放置标记'],
  drawRect: ['单击放置首个顶点', '单击完成绘制'],
  snap: ['拖动编辑顶点', '拖动新增顶点'],
  modifyScaleRotate: ['拖动旋转或缩放', '拖动缩放', '拖动旋转'],
  translate: ['拖动移动元素'],
};

通过setLayerStyle方法可以自定义绘制过程中的样式,支持修改的样式及默认样式如下:

const defaultStyle = {
  fillColor: 'white',
  fillOpacity: 0.5,

  fillActiveColor: 'white',
  fillActiveOpacity: 0.5,

  lineColor: '#2681ff',
  lineWidth: 2,
  lineOpacity: 1,
  lineDasharray: null,

  lineActiveColor: '#2681ff',
  lineActiveWidth: 2,
  lineActiveOpacity: 1,

  pointColor: '#2681ff',
  pointRadius: 4,
  pointStrokeColor: 'white',
  pointStrokeWidth: 1,
  pointStrokeOpacity: 1,
  pointOpacity: 1,

  pointActiveColor: '#2681ff',
  pointActiveRadius: 4,
  pointActiveStrokeColor: 'white',
  pointActiveStrokeWidth: 1,
  pointActiveStrokeOpacity: 1,
  pointActiveOpacity: 1,

  guideFillColor: 'white',
  guideFillOpacity: 0.8,

  guideLineColor: '#f46a00',
  guideLineWidth: 2,
  guideLineOpacity: 1,
  guideLineDasharray: null,

  guideOutlineColor: 'white',
  guideOutlineWidth: 4,
  guideOutlineOpacity: 1,
  guideOutlineDasharray: null,

  guidePointColor: '#f46a00',
  guidePointRadius: 4,
  guidePointStrokeColor: 'white',
  guidePointStrokeWidth: 1,
  guidePointStrokeOpacity: 1,
  guidePointOpacity: 1,
};

setLayerStyle(style: IEditOptions['layerStyle']): void;

通过监听edit对象的事件,可以获取绘制的内容:

edit.on('changeEnd', (e) => console.log(e));

其他对象调用方法:

addTo(map: AtlasMap): void;

remove(): void;

setActive(active: boolean): void;

clear(): void;

setLayerOrder(order: number): void;

setVisible(visible: boolean): void;

删除绘制元素:

import { AtlasMap, Edit, FillLayer, GeoJsonSource, RasterLayer, RasterSource } from '@datav-atlas/map';
import React, { useEffect, useState } from 'react';

export default () => {
  const [edit, setEdit] = useState<Edit>();
  useEffect(() => {
    //初始化地图应用
    const map = new AtlasMap('container', {
      crs: 'EPSG:3857',
      center: [119.87512573588158, 30.06950277327222],
      zoom: 8,
      pitch: 0,
      rotate: 0,
    });

    // 添加图层用于存储绘制要素
    const circleSource = new GeoJsonSource({
      id: 'circle',
      vector: false,
      data: {
        type: 'FeatureCollection',
        features: [
        ],
      },
    });

    const circleLayer = new FillLayer({
      id: 'circle',
      source: circleSource,
      interaction: { click: true },
      style: {
        color: 'orange',
        opacity: 0.7,
        showOutline: true,
        outlineColor: 'white'
      },
      order: 100
    });

    circleLayer.on('click', e => {
      if (e.feature) {
        alert(`删除要素${e.feature.id}`);
        const { id } = e.feature;
        const data = circleSource.data;
        data.features = data.features.filter(item => item.id !== id);
        circleSource.setData(data);
      }
    })

    const baseMap = new RasterLayer({
      id: 'base',
      source: new RasterSource({
        id: 'base',
        data: 'https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
        maxzoom: 18,
        tileSize: 256,
      }),
      order: 0,
    });

    const edit = new Edit({
      id: 'test-edit',
      mode: 'drawCircle',
      modeOption: {
        circleSeg: 100,
      },
      layerStyle: {
        fillColor: '#fff',
        fillOpacity: 0.5,
      },
    });

    edit.setActive(true);

    edit.on('changeEnd', (e) => {
      // 要素变更时添加到circleLayer中
      if (e.trigger === "feature:remove") return;
      circleSource.setData(e.fill);
    });

    circleLayer.addTo(map);
    baseMap.addTo(map);
    edit.addTo(map);

    setEdit(edit);

    return () => {
      map.destroy();
    };
  }, []);
  return (
    <div style={{ height: '600px' }}>
      <div style={{ height: 500 }} id="container"></div>
      <div style={{ height: 100, width: '100%' }}>
        <button
          type="button"
          onClick={() => {
            edit?.setActive(true);
          }}
        >
          {'开始绘制'}
        </button>

        <button
          type="button"
          onClick={() => {
            edit?.setActive(false);
            // 结束编辑时情况Edit内的要素
            edit?.clear();
          }}
        >
          {'结束绘制'}
        </button>
      </div>
    </div>
  );
};

通过mask后期实现要素筛选:

import {
  AtlasMap,
  CircleLayer,
  Edit,
  FillLayer,
  GeobufSource,
  GeoJsonSource,
  RasterLayer,
  RasterSource,
} from '@datav-atlas/map';
import React, { useEffect, useState } from 'react';

export default () => {
  const [edit, setEdit] = useState<Edit>();

  useEffect(() => {
    //初始化地图应用
    const map = new AtlasMap('container', {
      crs: 'EPSG:3857',
      center: [5.730675363345516, 45.179183821759295],
      zoom: 12.5,
      pitch: 0,
      rotate: 0,
    });

    const effect = map._ins.addEffect({
      id: 'filter',
      effects: [
        
      ],
    });

    // @ts-ignore
    window.gimap = map;

    const pointSource = new GeobufSource({
      id: 'point',
      vector: false,
      data: 'https://vis-data-server.oss-cn-hangzhou.aliyuncs.com/demo-data/lights.geobuf.gzip',
    });

    const pointLayer = new CircleLayer({
      id: 'point',
      effect: 'filter',
      source: pointSource,
      style: {
        color: 'orange',
        opacity: 0.7,
        radius: 3,
        units: 'pixels',
        strokeColor: 'white',
        strokeWidth: 1,
      },
      order: 100,
    });

    const circleSource = new GeoJsonSource({
      id: 'circle',
      vector: false,
      data: {
        type: 'FeatureCollection',
        features: [],
      },
    });

    const circleLayer = new FillLayer({
      id: 'circle',
      source: circleSource,
      interaction: { click: true },
      style: {
        color: 'orange',
        opacity: 0.2,
        showOutline: true,
        outlineColor: 'white',
      },
      order: 50,
    });

    const baseMap = new RasterLayer({
      id: 'base',
      source: new RasterSource({
        id: 'base',
        data: 'https://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
        maxzoom: 18,
        tileSize: 256,
      }),
      order: 0,
    });

    const edit = new Edit({
      id: 'test-edit',
      mode: 'drawCircle',
      modeOption: {
        circleSeg: 100,
      },
      layerStyle: {
        fillColor: '#fff',
        fillOpacity: 0.5,
      },
    });

    edit.setActive(true);

    edit.on('changeEnd', (e) => {
      if (e.trigger === 'feature:remove') return;
      circleSource.setData(e.fill);
      effect.addPass({
        type: 'mask',
        options: {
          maskLayers: ['circle'],
        },
      });
    });

    circleLayer.addTo(map);
    baseMap.addTo(map);
    edit.addTo(map);
    pointLayer.addTo(map);

    setEdit(edit);

    return () => {
      map.destroy();
    };
  }, []);

  return (
    <div style={{ height: '600px' }}>
      <div style={{ height: 500 }} id="container"></div>
      <div style={{ height: 100, width: '100%' }}>
        <button
          type="button"
          onClick={() => {
            edit?.setActive(true);
          }}
        >
          {'开始绘制'}
        </button>

        <button
          type="button"
          onClick={() => {
            edit?.setActive(false);
            edit?.clear();
          }}
        >
          {'结束绘制'}
        </button>
      </div>
    </div>
  );
};

联系我们

若在使用过程中有任何问题,请联系我们获取开发指导。