# L7 — Full Documentation > 蚂蚁集团 AntV 数据可视化团队推出的基于 WebGL 的开源大规模地理空间数据可视分析引擎。 - [Resource index](/llms.txt) - Canonical site: https://l7.antv.antgroup.com/zh/ - Source repository: https://github.com/antvis/L7 - Languages: zh ## 中文文档 ### api #### Component 组件 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/component/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/component.md - Description: Component 组件 --- title: "Component 组件" description: "Component 组件" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/component/" --- L7 中的 Component 主要包含以下三种类型: - [Control 控件类型](/zh/api/component/control):指的是悬停在地图四周,可以对地图以及图层等元素进行信息呈现或交互的组件。 - [Popup 气泡类型](/zh/api/component/popup):用于在地图上指定经纬度位置展示气泡,气泡内容完全交由开发者自定义。 - [Marker 类型](/zh/api/component/marker):与 Popup 相似,不同的是 Marker 展示的内容不会在气泡内展示,而是完全交由开发者自定义。 #### Popup 信息框 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/popup/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/popup.md - Description: Popup 信息框 --- title: "Popup 信息框" description: "Popup 信息框" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/popup/" --- Popup 是用于在地图上指定经纬度位置,展示自定义内容的气泡。 ## 说明 Popup 的锚点位置是由经纬度来表达的,当地图缩放/平移时,Popup 会自动计算相对于当前地图的坐标并且自动位移。换句话说,如果开发者需要在地图的**指定经纬度位置**展示信息气泡,可以考虑使用 Popup 组件来实现对应效果。 开发者可以自定义 Popup 主体展示内容: - 纯文本可以通过 `text` 配置或者 `setText` 方法控制 Popup 的展示文本。 - 自定义 DOM 可以通过 `html` 配置或者 `setHTML` 方法,支持传入 HTML 字符串或者 DOM 元素或数组的方式控制 Popup 的展示内容。 ## 使用 [示例](/zh/examples/component/popup/popup/) ```ts import { Scene, Popup } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMapV2({ // ... }), }); scene.on('loaded', () => { const popup = new Popup({ // 初始锚点经纬度 lngLat: { lng: 120, lat: 30, }, // Popup 标题 title: 'Popup Title', // Popup 内容 html: 'Popup Content', }); scene.addPopup(popup); // 更新 Popup 锚点经纬度 popup.setLngLat({ lng: 130, lat: 40, }); // 更新 Popup 内容 popup.setHTML('New Popup Content'); }); ``` ## 配置 | 名称 | 说明 | 类型 | 默认值 | | ------------------ | ------------------------------------------------------------------------ | ------------------------------ | ---------- | | lngLat | Popup 所在的经纬度 | `{ lng: number; lat: number }` | - | | text | Popup 内容展示的文本内容 | `string` | - | | html | Popup 内容展示的自定义 HTML,可以传 HTML 字符串,也可以传 DOM 对象或数组 | [ElementType](#elementtype) | - | | title | Popup 标题展示的自定义 HTML,可以传 HTML 字符串,也可以传 DOM 对象或数组 | [ElementType](#elementtype) | - | | closeOnClick | 点击地图区域时,是否关闭当前 Popup | `boolean` | `false` | | closeOnEsc | 点击 Esc 键时,是否关闭当前 Popup | `boolean` | `false` | | maxWidth | Popup 的最大宽度 | `string` | `240px` | | anchor | Popup 箭头位置,可以控制 Popup 相对于经纬度点的展示位置 | [AnchorType](#anchortype) | `'bottom'` | | offsets | Popup 相对于锚点的偏移 | `[number, number]` | `[0, 0]` | | autoPan | 当 Popup 展示或者位置发生变化时,地图是否要自动平移至 Popup 所在位置 | `boolean` | `false` | | autoClose | 当有其他 Popup 展示时,是否自动关闭当前气泡 | `boolean` | `true` | | followCursor | Popup 是否跟随光标移动,若设为 `true`,则 `lngLat` 配置无效 | `boolean` | `false` | | closeButton | 是否展示关闭 Popup 图标 | `boolean` | `true` | | closeButtonOffsets | 关闭 Popup 图标的相对偏移 | `[number, number]` | - | | stopPropagation | Popup 上的鼠标事件是否要阻止其冒泡 | `boolean` | `true` | ### ElementType ```ts type ElementType = HTMLElement | HTMLElement[] | DocumentFragment | Text | string; ``` ### AnchorType ```ts type AnchorType = | 'center' | 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'right'; ``` ## 方法 | 名称 | 说明 | 类型 | | ---------- | --------------------------- | -------------------------------------------------------------------- | | getOptions | 获取当前 Popup 配置 | `() => IPopupOption` | | setOptions | 更新当前 Popup 配置 | `(newOption: Partial) => this` | | show | 显示 Popup | `() => this` | | hide | 隐藏 Popup | `() => this` | | getIsShow | 判断当前气泡是否展示 | `() => boolean` | | setTitle | 设置 Popup 标题展示的 HTML | `(title: ElementType) => this` | | setHTML | 设置 Popup 内容展示的 HTML | `(html: ElementType) => this` | | setText | 设置 Popup 内容展示的文本 | `(text: string) => this` | | setLngLat | 设置 Popup 锚点所在经纬度 | `(lngLat: { lng: number; lat: number } \| [number, number]) => this` | | panToPopup | 将地图平移至当前 Popup 位置 | `() => this` | ## 事件 | 名称 | 说明 | 类型 | | ----- | ------------------ | ------------ | | open | Popup 被添加时触发 | `() => void` | | close | Popup 被移除时触发 | `() => void` | | show | Popup 显示时触发 | `() => void` | | hide | Popup 隐藏时触发 | `() => void` | #### DebugService - Canonical page: https://l7.antv.antgroup.com/zh/api/debug/debugservice/ - Markdown source: https://l7.antv.antgroup.com/zh/api/debug/debugservice.md - Description: DebugService --- title: "DebugService" description: "DebugService" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/debug/debugservice/" --- ## 简介 L7 在通过 debugService 的形式对外提供调试服务,通过 debugService 用户可以获得一些有助于性能监控的信息。 ### serEnable(enable: boolean) 用户可以通过 scene 初始化的时候和 debugService 提供的方法来开启监控。 ```js // 可以在 scene 初始化的时候打开监控 const scene = new Scene({ debug: true, // 默认为 false }); // 可以通过 debugService 单独控制监控 const debugService = scene.getDebugService(); debugService.serEnable(true); // 开启监控 ``` ### getLog(field: undefined | string | string[]): ILog[] | ILog | undefined 用户通过 getLog 方法获取日志,通过传入不通的参数,用户可以准确获得自己需要的日志内容。 ```js // 获取地图初始化日志 debugService.getLog('map'); // map 为固定值 // 在获取图层的创建日志时,为了获取到全部的数据,需要在 layer 创建完成之后获取 layer.on('inited', () => { debugService.getLog(layer.id); // 获取单个图层创建日志 }); layerAllLoad([pointLayer1, pointLayer2], () => { // layerAllLoad 自己实现监听 debugService.getLog([pointLayer1.id, pointLayer2.id]); // 获取多个图层创建日志 }); // 获取所有日志 debugService.getLog(); ``` - 通过 getLog 方法可以获得如下的日志信息 ```js const enum IDebugLog { MapInitStart = 'mapInitStart', // 地图初始化时间 LayerInitStart = 'layerInitStart', // 图层初始化开始时间 LayerInitEnd = 'layerInitEnd', // 图层初始化结束时间 SourceInitStart = 'sourceInitStart',// souce 初始化开始时间 SourceInitEnd = 'sourceInitEnd', // souce 初始化结束时间 // scale:将数据进行 scale 映射处理 => 将数据从定义域转化到值域 // 如: layer.size('v', [1, 10]); // 根据字段 v 表示的定义域将 size 的结果映射到 1 ~ 10 之间 ScaleInitStart = 'scaleInitStart', // scale 初始化开始时间 ScaleInitEnd = 'scaleInitEnd', // scale 初始化结束时间 // mapping:构建渲染数据 MappingStart = 'mappingStart', // mapping 初始化开始时间 MappingEnd = 'mappingEnd', // mapping 初始化结束时间 // build model:构建渲染使用的程序对象、构建网格、纹理等 BuildModelStart = 'buildModelStart',// souce 初始化开始时间 BuildModelEnd = 'buildModelEnd', // souce 初始化结束时间 } ``` ### renderDebug(enable: boolean) debugService 提供了监听图层渲染时间的便捷方法, 通过 renderDebug 开启。 ### on(name: string, options: any) debugService 支持事件监听,常用与监听渲染。 ```js debugService.on('renderEnd', renderInfo => { const { renderUid, // 当前帧渲染唯一编号 renderStart, // 当前帧渲染开始时间 renderEnd, // 当前帧渲染结束时间 renderDuration // 当前帧渲染时间 } = renderInfo; ... } ``` ### off(name: string, func: Function) debugService 事件取消监听。 #### Heatmap - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/heatmap/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/heatmap.md - Description: Heatmap --- title: "Heatmap" description: "Heatmap" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/heatmap/" --- ## 简介 热力图以特殊高亮的形式显示数据在地理区域的聚集程度,L7 提供了多种表现形式的热力图,通过切换 `shape` 参数,用户可以得到不同类型的热力图。 | shape 值 | 说明 | | ---------------- | -------------- | | `heatmap` | 经典高斯热力图 | | `heatmap3D` | 3D 热力图 | | `hexagon` | 六边形聚合 | | `hexagonColumn` | 六边形柱状聚合 | | `square` | 正方形聚合 | | `squareColumn` | 正方形柱状聚合 | | `triangle` | 三角形聚合 | | `triangleColumn` | 三角形柱状聚合 | | `cylinder` | 圆柱聚合 | ```javascript import { HeatmapLayer } from '@antv/l7'; const layer = new HeatmapLayer() .source(data) .shape('heatmap') .size('mag', [0, 1.0]) // weight 映射通道 .style({ radius: 20, rampColors: { colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'], positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], }, }); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## source 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 🌟 热力图的数据使用和点图层保持一致。 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 var data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [120, 30], ... ] }, }, ], }; var layer = new HeatmapLayer() .source(data) ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; var layer = new HeatmapLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30 }, ... ] var layer = new HeatmapLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', } }) ``` ## shape `shape` 方法用于指定热力图层绘制热力的类型,支持经典热力、蜂窝热力、网格热力等多种类型。 ```js layer.shape('heatmap'); ``` | shape 值 | 说明 | | ---------------- | ---------------------------------- | | `heatmap` | 2D 经典高斯热力图 | | `heatmap3D` | 3D 热力图,在 Z 轴方向展示热力强度 | | `hexagon` | 六边形网格(2D 平面) | | `hexagonColumn` | 六边形柱状网格(3D 拉伸) | | `square` | 正方形网格(2D 平面) | | `squareColumn` | 正方形柱状网格(3D 拉伸) | | `triangle` | 三角形网格(2D 平面) | | `triangleColumn` | 三角形柱状网格(3D 拉伸) | | `cylinder` | 圆柱聚合(3D 拉伸) | ### shape('heatmap') `shape` 为 `heatmap` 时,绘制 2D 经典高斯热力图,通过颜色渐变反映数据密度。 ### shape('heatmap3D') `shape` 为 `heatmap3D` 时,绘制 3D 热力图,在 Z 轴方向通过高度反映热力强度,需开启地图的 3D 视角。 ### shape('hexagon') / shape('hexagonColumn') 基于六边形网格的聚合热力,`hexagon` 为 2D 填充,`hexagonColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'hexagon'` 使用。 ### shape('square') / shape('squareColumn') 基于正方形网格的聚合热力,`square` 为 2D 填充,`squareColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'square'` 使用。 ### shape('triangle') / shape('triangleColumn') 基于三角形网格的聚合热力,`triangle` 为 2D 填充,`triangleColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'triangle'` 使用。 ### shape('cylinder') 基于圆形网格的聚合热力,以 3D 圆柱形式展示。需配合 `transforms` 中 `type: 'grid'` 使用。 ### transforms 网格热力和蜂窝热力的实现依赖配置 `transforms` 的参数,[具体说明使用](/zh/api/source/source/#transforms)。 ```js fetch('https://gw.alipayobjects.com/os/basement_prod/513add53-dcb2-4295-8860-9e7aa5236699.json') .then((res) => res.json()) .then((data) => { const layer = new HeatmapLayer({}) .source(data, { transforms: [ { type: 'hexagon', size: 100, field: 'h12', method: 'sum', }, ], }) .size('sum', [0, 600]) .shape('hexagonColumn') .style({ coverage: 0.8, angle: 0, }) .color( 'sum', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#CEF8D6', ].reverse(), ); scene.addLayer(layer); }); ``` ## size size 方法用于映射权重字段,将数值范围归一化到 `[0, 1]`,作为热力强度使用。 ```js layer.size('weight', [0, 1.0]); ``` | 参数 | 类型 | 说明 | | ----- | ------------------ | ------------------------------- | | field | `string` | 数据字段名,用于映射热力权重 | | range | `[number, number]` | 映射的值域范围,通常为 `[0, 1]` | ## scale `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` ## style `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 🌟 蜂窝热力图和网格热力图的 `style` 样式可以参考实际绘制的图层。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | ### heatmap `shape` 为 `heatmap`、`heatmap3D` 类型的时候,绘制经典热力图。 | style | 类型 | 描述 | 默认值 | | ---------- | -------- | ------------ | ------ | | intensity | `number` | 热力的强度 | `10` | | radius | `number` | 热力点的半径 | `10` | | rampColors | `number` | 热力的色值 | `1` | #### rampColors - colors 颜色数组 - positions 数据区间 配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。 ⚠️ colors, positions 的长度要相同 ```javascript layer.style({ rampColors: { colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'], positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], }, }); ``` ### hexagon 绘制蜂窝热力图。 | style | 类型 | 描述 | 默认值 | | -------- | -------- | ------------ | ------ | | angle | `number` | 图形旋转角度 | `0` | | coverage | `number` | 图形覆盖比率 | `0.9` | ### grid 绘制网格热力图。 | style | 类型 | 描述 | 默认值 | | -------- | -------- | ------------ | ------ | | coverage | `number` | 图形覆盖比率 | `1` | ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### ImageLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/image_layer/imagelayer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/image_layer/imagelayer.md - Description: ImageLayer --- title: "ImageLayer" description: "ImageLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/image_layer/imagelayer/" --- ## 简介 图片图层将图片叠加到地图上,需要指定图片的经纬度范围(`extent`)和数据解析类型。支持 PNG、JPG、WebP 等常见图片格式。 ```javascript import { ImageLayer } from '@antv/l7'; const layer = new ImageLayer({}); layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## source `imagelayer` 通过提供在线图片的 `url` 指定数据,通过 `extent` 指定图片在地图上的矩形范围的位置。 ```js layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` 也可通过 `coordinates` 指定一系列坐,来定义图片在地图上的不规则形状范围的位置。 ```js layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', coordinates: [ [100.959388, 41.619522], [101.229887, 41.572654], [101.16971, 41.377836], [100.900015, 41.424628], ], }, }); ``` ## style `imagelayer` 的 `style` 参数只支持 `opacity`。 | style | 类型 | 描述 | 默认值 | | ---------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | | brightness | `number` | 图形的亮度 | `1` | | contrast | `number` | 图形的对比度 | `1` | | saturation | `number` | 图形的饱和度 | `1` | | gamma | `number` | 图形的伽马值 | `1` | ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### LineLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/linelayer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/linelayer.md - Description: LineLayer --- title: "LineLayer" description: "LineLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/linelayer/" --- ## 简介 线图层通过一组经纬度数据组来描述地图上的一条或者多条路径。通过路径的类型,将其区分为路径、弧线、3D 弧线以及其他的类型。 用户可以通过配置 `shape` 参数来选择线的类型,同时通过 `style`、`size`、`color` 方法调整线的样式。 ```js import { LineLayer } from '@antv/l7'; const layer = new LineLayer() .source([{ lng: 120, lat: 30, lng1: 125, lat1: 30 }], { parser: { type: 'json', x: 'lng', y: 'lat', x1: 'lng1', y1: 'lat1', }, }) .shape('line') .size(2) .color('#f00'); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## source 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 const data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'LineString', coordinates: [ [106.5234375, 57.51582286553883], [136.40625, 61.77312286453146], ], }, }, ], }; const layer = new LineLayer().source(data); ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; new LineLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30, lng1: 125, lat1: 30 }, ... ] var layer = new LineLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', x1: 'lng1', y1: 'lat1' } }) ``` ## shape `shape` 方法用于指定线图层绘制什么样的线。 ### shape('line') 绘制路径图。 `line` 路径是最普通的线图层,支持配置宽度和高度,支持配置纹理和动画。 ```js layer.shape('line'); ``` ### shape('arc') `arc` 弧线通过贝塞尔曲线算法计算出弧线的的路径,支持配置纹理和动画。 ```js layer.shape('arc'); ``` ### shape('arc3d') `arc3d` 3d 弧线是在垂直地图两点之间的弧线,具有高度,支持配置纹理和动画。 ```js layer.shape('arc3d'); ``` ### shape('greatcircle') `greatcircle` 大圆航线是地图两个点最近距离的连线,支持配置纹理和动画。 ```js layer.shape('greatcircle'); ``` ### shape('wall') `wall` 是垂直地图的围墙,支持配置高度,纹理和动画。 ```js layer.shape('wall'); ``` ### shape('simple') `simple` 线图层,宽度始终为 `1px`。 ```js layer.shape('simple'); ``` ### shape('flowline') `flowline` 流向图, 2.17 版本新增 ## color `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` ## size 线图层的 `size` 方法可以设置线的宽度和高度。 ### ILineSize: number | [number, number] - size 类型为 number 则表示 line 的宽度 - size 类型为 [number , number] 分别表示宽度和高度 ```javascript lineLayer.size(1); // 线的宽度为 1 lineLayer.size([1, 2]); // 宽度为1,高度2 ``` ### size(width: ILineSize) 线图层可以直接设置宽度值。图层中所有的线使用一个宽度。 ```js layer.size(2); ``` ### size(field: string) 线图层的宽度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source({ type: 'Feature', properties: { lineSize: 2, }, geometry: { type: 'LineString', coordinates: [ [119.988511, 30.269614], [119.9851, 30.269323], [119.99271, 30.22088], ], }, }); layer.size('lineSize'); ``` ### size(field: string, domain: ILineSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => ILineSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为线图层实际的宽高。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` ## scale `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` ## style `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 数据映射 | 默认值 | | ------- | -------- | ------------ | -------- | ------ | | opacity | `number` | 图形的透明度 | 支持 | `1` | ### line `shape` 为 `line` 的普通线图层。 - [line](/zh/api/line_layer/shape#shapeline) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------------------------- | -------------------------- | ------------ | ----------- | | stroke | `string` | 图形边框颜色 | 是 | `#fff` | | strokeWidth | `number` | 图形边框半径 | 否 | `0` | | blur | `[number, number, number]` | 图形模糊分布 | 否 | `[1, 1, 1]` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | ### arc `shape` 为 `arc` 平面的弧线。 - [arc](/zh/api/line_layer/shape#shapearc) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------- | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | thetaOffset | `number` | 弧线的弧度参数 | 是 | `0.314` | ### arc3d `shape` 为 `arc3d` 的弧线图层。 - [arc3d](/zh/api/line_layer/shape#shapearc3d) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------ | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | | thetaOffset | `number` | 弧线的弧度参数 | 是 | `1` | ### greatcircle `shape` 为大圆弧线图层。 - [greatcircle](/zh/api/line_layer/shape#shapegreatcircle) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------ | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | ### flowline | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | ----------------- | ------------------------ | ------------ | ------- | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | strokeOpacity | `number` | 描边透明度 | 否 | `30` | | stroke | `number` | 描边颜色 | 是 | `#000` | | strokeWidth | `number` | 描边宽度 | `1` | 否 | | gapWidth | `number` | 不同方向两条线间距 | `2` | 否 | | offsets | `[number,number]` | 两端偏移量,支持数据映射 | 是 | `[0,0]` | flowline opacity 和 offsets 支持数据映射,数据驱动设置数据大小 #### opacity ```ts layer.style({ opacity: { field: 'count', // 映射字段 value: [0.2,0.4,0.6,0.8], // 映射值,支持回调函数,支持设置scale } // field 和 value 等同于 layer.color('count',[0.2,0.4,0.6,0.8]) ``` #### offsets ```ts layer.style({ offsets:{ field: 'count', values:() => { return [10 + Math.random()*20, 10 + Math.random()*20] } }) ``` ### wall `shape` 为 `wall` 地理围栏弧线图层。 - [wall](/zh/api/line_layer/shape#shapewall) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) ### simple `shape` 为 `simple` 简单线图层。 - [simple](/zh/api/line_layer/shape#shapesimple) - [支持渐变](/zh/api/line_layer/style#linear) ### linear - line、arc、arc3d、greatcircle、wall、simple 线图层支持配置渐变效果,在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 | style | 类型 | 描述 | 默认值 | | ----------- | ------------ | ---------- | ---------- | | sourceColor | `IColor` | 线起始颜色 | `/` | | targetColor | `IColor` | 线结尾颜色 | `/` | | linearDir | `ILinearDir` | 线渐变方向 | `vertical` | #### IColor ```js const color = `rgb(200, 100, 50)`; const color2 = '#ff0'; ``` #### ILinearDir - vertical 纵向(沿线方向) - horizontal 横向 ```js type ILinearDir = 'vertical' | 'horizontal'; ``` ### texture - line、arc、arc3d、greatcircle 线图层支持纹理以及纹理动画,纹理样式有自己的参数。 | style | 类型 | 描述 | 默认值 | | ------------ | --------------- | ------------------------------ | -------- | | lineTexture | `boolean` | 时候开启纹理能力 | `false` | | textureBlend | `ITextureBlend` | 纹理混合方式 | `normal` | | iconStep | `number` | 纹理贴图在线图层上面排布的间隔 | `100` | #### ITextureBlend 线图层的纹理在和线本身的颜色进行融合的时候支持两种,`normal` 和 `replace`。 - normal 纹理和线颜色混合 - replace 使用纹理替换线颜色 ```js type ITextureBlend = 'normal' | 'replace'; ``` #### texture advance ✨ animate 当线图层 (shape 为 arc/arc3d) 开启动画模式的时候,纹理在线图层上的分布还会和 animate 的参数相关 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` ### dash - line、arc、arc3d、greatcircle 线图层支持配置虚线,虚线有自己额外的样式参数。 ```js layer.style({ lineType: 'dash' dashArray: [5, 5] }) ``` | style | 类型 | 描述 | 默认值 | | --------- | ------------ | ---------- | ------- | | lineType | `ILineType` | 线的类别 | `solid` | | dashArray | `IDashArray` | 虚线的间隔 | `/` | #### ILineType - solid 实线 - dash 虚线 #### IDashArray `dashArray` 只有在 `ILineType` 为 `dashed` 的时候才会生效。 ```js // len1 实线长度 len2 间隔长度 type IDashArray = [len1: number, len2: number] ``` ## animate 线图层图层在开启 `animate` 方法后会得到沿线方向的线动画。 ### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` ### IAnimateOption ```javascript interface IAnimateOption { enable: boolean; speed: number; rings: number; } ``` ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) ## texture 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### 地图 Map - Canonical page: https://l7.antv.antgroup.com/zh/api/map/map/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/map.md - Description: 地图 Map --- title: "地图 Map" description: "地图 Map" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/map/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建,创建管理 只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - Map 独立地图引擎,不需要底图、或者加载地图瓦片服务,不需要 Token ## import ```javascript import { Map } from '@antv/l7-maps'; ``` ## Map 实例化 ```ts import { Scene, PointLayer } from '@antv/l7'; import { Map } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Map({ zoom: 10, minZoom: 0, maxZoom: 18, }), }); scene.on('loaded', () => { // 添加地图底图 const layer = new RasterLayer(); layer.source( 'https://webrd0{1-3}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', tileSize: 256, minZoom: 2, maxZoom: 18, }, }, ); scene.addLayer(layer); }); ``` ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### PlaneGeometry - Canonical page: https://l7.antv.antgroup.com/zh/api/other/plane/ - Markdown source: https://l7.antv.antgroup.com/zh/api/other/plane.md - Description: PlaneGeometry --- title: "PlaneGeometry" description: "PlaneGeometry" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/other/plane/" --- ## 简介 PlaneGeometry 是 L7 提供的通用的平面几何体图形,表现为可以自定义为位置,大小和分段数的贴地矩形。 ### demo 设置普通矩形 ```javascript import { Scene, GeometryLayer } from '@antv/l7'; const layer = new GeometryLayer() .shape('plane') .style({ opacity: 0.8, width: 0.074, height: 0.061, center: [120.1025, 30.2594], }) .active(true) .color('#ff0'); scene.addLayer(layer); ``` [在线案例](/zh/examples/geometry/geometry/plane/) 设置 3D 地形模式 ```javascript import { Scene, GeometryLayer } from '@antv/l7'; const layer = new GeometryLayer().shape('plane').style({ width: 0.074, height: 0.061, center: [120.1025, 30.2594], widthSegments: 200, heightSegments: 200, terrainClipHeight: 1, mapTexture: 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ', terrainTexture: 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ', rgb2height: (r, g, b) => { let h = (r * 255.0 * 256.0 * 256.0 + g * 255.0 * 256.0 + b * 255.0) * 0.1; h = h / 200 - 12750; h = Math.max(0, h); return h; }, }); scene.addLayer(layer); ``` [在线案例](/zh/examples/geometry/geometry/terrain/) ### source 🌟 PlaneGeometry 不需要设置 source,我们在 style 中通过 center 赋予其位置信息。 ### style PlaneGeometry 主要通过 style 方法设置位置、大小以及其他属性。 #### center: [lng: number, lat: number] 设置 PlaneGeometry 的位置,定位是 PlaneGeometry 的几何中心。PlaneGeometry 贴地放置。 #### width: number 设置 PlaneGeometry 的宽度,单位是经度。 #### height: number 设置 PlaneGeometry 的高度,单位是纬度。 #### widthSegments: number 设置 PlaneGeometry 在 纬度方向上的分段数。 #### heightSegments: number 设置 PlaneGeometry 在 经度方向上的分段数。 #### mapTexture: string PlaneGeometry 纹理贴图 URL。 #### terrainTexture: string PlaneGeometry 高度贴图 URL,当存在该参数的时候 L7 会自动解析高程信息。 #### terrainClipHeight: number 指定 3D 地形的裁剪高度。在一些情况下我们可能只需要保留存在丘陵山地的部分,通过这个参数我们可以指定地形高度低于这个参数值的部分不显示. #### rgb2height: (r: number, g: number, b: number) => number 这是一个回调函数,参数是 L7 解析出的地形贴图的 rgb 信息,用户可以使用该函数定义高度值的计算逻辑(不同的地形贴图计算逻辑不同)。 🌟 widthSegments/heightSegments 指定 planeGeometry 的分段数,分段越多,地形越平滑,同时性能消耗越大。 #### PointLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/pointlayer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/pointlayer.md - Description: PointLayer --- title: "PointLayer" description: "PointLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/pointlayer/" --- ## 简介 点图层通过一组经纬度数据来描述一系列点在地图上的位置,这些点可以是普通的圆点,也可以是文字、图标、柱子等。 用户可以通过配置 `shape` 参数来选择点的类型,同时通过 `style`、`size`、`color` 方法调整点的样式。 ```javascript import { PointLayer } from '@antv/l7'; const layer = new PointLayer({ zIndex: 2, }) .source(data.list, { type: 'array', x: 'j', y: 'w', }) .shape('cylinder') .size('t', (level) => { return [4, 4, level + 40]; }) .color('t', [ '#002466', '#105CB3', '#2894E0', '#CFF6FF', '#FFF5B8', '#FFAB5C', '#F27049', '#730D1C', ]); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## source 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 var data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [120, 30], ... ] }, }, ], }; var layer = new PointLayer() .source(data) ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; var layer = new PointLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30 }, ... ] var layer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', } }) ``` ## shape `shape` 方法用于指定点图层绘制什么样的图形,如绘制三角形或者是正方形,还是文字、图标之类的。 ### shape(fillShape: IFillShape) 点图层的贴地的几何图形,如圆形、正方形、三角形等。 🌟 若是使用简单的圆点图层,建议使用 `simple` 代替 `circle` 以获得更好的性能。 ```js // shape 支持的各种形状 type IFillShape = | 'circle' | 'square' | 'hexagon' | 'triangle' | 'pentagon' | 'octogon' | 'hexagram' | 'rhombus' | 'vesica'; layer.shape('circle'); ``` ### shape(column: IColumn) 点的类型为垂直地图的柱子。 ```js type IColumn = 'cylinder' | 'triangleColumn' | 'hexagonColumn' | 'squareColumn'; layer.shape('cylinder'); layer.shape('triangleColumn'); layer.shape('hexagonColumn'); layer.shape('squareColumn'); ``` ### shape('simple') `simple` 点精灵是特殊的点图层,始终面向相机,且大小受到设备的限制。 ```js layer.shape('simple'); ``` ### shape('dot') `dot` 点精灵是特殊的点图层,始终面向相机,且大小受到设备的限制。 ```js layer.shape('dot'); ``` ### shape(field: string, 'text') 绘制文字,第一个参数为数值中的字段,第二个参数固定为 `text`。 ```js const point = new PointLayer() .source([{ lng: 120, lat: 30, name: 'test' }], { parser: 'json', x: 'lng', y: 'lat', }) .shape('test', 'text'); ``` ### shape(iconName: string) `shape` 的值为 `scene.addImage` 全局添加的图片资源的名称。 ```js 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( [ { longitude: 120, latitude: 30, name: 'name', }, ], { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }, ) .shape('name', ['00', '01', '02']) // shape 支持映射写法 .size(25); scene.addLayer(imageLayer); const imageLayer2 = new PointLayer() .source( [ { longitude: 122, latitude: 30, name: 'name', }, ], { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }, ) .shape('00') // shape 直接传值 .size(25); scene.addLayer(imageLayer2); ``` ### shape('radar') ```js const layer = new PointLayer() .source( [ { lng: 120, lat: 30, }, ], { parser: { type: 'json', x: 'lng', y: 'lat', }, }, ) .size(25) .color('#f00') .shape('radar') .animate(true); ``` 🌟 雷达图需要设置 `animate` 为 `true` ## color `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` ## size `size` 方法用于设置点图层图形的大小。 ### IPointSize: number |[number, number] | [number, number, number] - size 类型为 number 则表示 point 的半径 - size 类型可以为 [number, number]|[number, number, number] 表示柱子的半径和高度 ```javascript pointLayer.size(1); pointLayer.size([2, 10]); // 柱子半径为 2x2.高为 10 pointLayer.size([2, 4, 10]); // 柱子半径为 2x4,高为 10 ``` ### size(width: IPointSize) 点图层可以直接设置半径。图层中所有的点使用一个宽度。 ```js layer.size(2); ``` ### size(field: string) 点图层的宽度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, r: 2, }, ]); layer.size('r'); ``` ### size(field: string, domain: IPointSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => IPointSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为点图层实际的半径。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` ## scale `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` ## style `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | #### 样式数据映射 默认样式配置为常量值,某些配置也支持数据映射,映射定义同 color、size参数一致。 - field: 映射字段 - value: 映射区间或者自定义回调函数 如: ```ts layer.style({ opacity:{ field:'name' value:[0.1,0.5,1], } }) ``` ### 2D shape `shape` 为平面图形、如三角形、正方等。 - [IFillShape](/zh/api/point_layer/shape#shapefillshape-ifillshape) | style | 类型 | 是否支持数据映射 | 描述 | 默认值 | | ------------- | -------------------------------------------------- | ---------------- | -------------------------------------------- | -------- | | stroke | `string` | 是 | 图形边框颜色 | `#fff` | | strokeWidth | `number` | 否 | 图形边框宽度 | `0` | | strokeOpacity | `number` | 否 | 图形边框透明度 | `1` | | blur | `number` | 否 | 图形模糊半径 | `0` | | offsets | `[number, number]` | 是 | 点偏移 | `[0, 0]` | | rotation | `number` | 是 | 旋转角度 | `0` | | anchor | [anchorType](/zh/api/point_layer/style#anchortype) | 是 | 图形锚点位置,控制图形相对于坐标点的对齐方式 | `center` | | raisingHeight | `number` | 否 | 抬升高度 | `0` | | heightfixed | `boolean` | 否 | 点大小单位 | `pixel` | #### unit - pixel 默认值 - meter 单位为米 ```js type IUnit = 'pixel' | 'meter'; ``` 点图层支持等面积点,点大小的单位是米,同样通过 size 方法设置大小 ```javascript import { PointLayer } from '@antv/l7'; const layer = PointLayer().source(data).shape('circle').size(100).color('#f00').style({ unit: 'meter', }); ``` 🌟 从 v2.7.9 版本开始支持高德地图、高德地图 2.0、Mapbox 地图 ### 3D column `shape` 为 3D 柱图。 - [IColumn](/zh/api/point_layer/shape#shapecolumn-icolumn) | style | 类型 | 描述 | 默认值 | | ----------- | --------- | -------------------- | ------- | | depth | `boolean` | 图形是否开启深度检测 | `true` | | pickLight | `boolean` | 拾取高亮是否计算光照 | `false` | | lightEnable | `boolean` | 颜色是否参与光照计算 | `true` | | heightfixed | `boolean` | 是否是固定高度 | `false` | ### 3D column linear 柱图支持配置渐变色,在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 | style | 类型 | 描述 | 默认值 | | ------------- | --------------- | ---------------- | ------ | | sourceColor | `color` | 柱子底部颜色 | `/` | | targetColor | `color` | 柱子顶部颜色 | `/` | | opacityLinear | `IOpcityLinear` | 柱子的透明度渐变 | `/` | #### color ```js const color = `rgb(200, 100, 50)`; const color2 = '#ff0'; ``` #### opacityLinear ```js type IDir = 'up' | 'down'; interface IOpcityLinear = { enable: boolean; dir: IDir; } ``` ### text `shape` 为文字。 - [text](/zh/api/point_layer/shape#shapefield-string-text) | style | 类型 | 描述 | 是否支持数据映射 | 默认值 | | ---------------- | -------------------------------------------------- | -------------------------- | ---------------- | ------------ | | opacity | `number` | 透明度 | 是 | `#fff` | | stroke | `string` | 图形边框颜色 | 是 | `#fff` | | strokeWidth | `number` | 图形边框颜色 | 否 | `0` | | textOffset | `[number, number]` | 文字的偏移 | 是 | `[0, 0]` | | textAnchor | [anchorType](/zh/api/point_layer/style#anchortype) | 文字对齐锚点 `text` | 是 | `center` | | spacing | `number` | 文字间隔 | 否 | `2` | | rotation | `number` | 旋转角度 | 是 | `0` | | padding | `number` | 文字内边框宽度 | 否 | `2` | | halo | `number` | 文字边缘光晕宽度 | 否 | `0.5` | | gamma | `number` | 文字的颜色参数 | 否 | `2` | | fontWeight | `string` | 文字的大小 | 否 | `400` | | fontFamily | [font](/zh/api/point_layer/style#font) | 字体 | 否 | `sans-serif` | | textAllowOverlap | `boolean` | 文字是否允许覆盖 | 否 | `false` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | #### anchorType 图形/文字对齐锚点,用于控制图形或文字相对于坐标点的对齐方式。 - 在 2D shape(如 `circle`、`square` 等)中通过 `anchor` 属性使用,控制图形相对于坐标点的位置 - 在 text shape 中通过 `textAnchor` 属性使用,控制文字相对于坐标点的位置 ```javascript export enum anchorType { 'CENTER' = 'center', 'TOP' = 'top', 'TOP-LEFT' = 'top-left', 'TOP-RIGHT' = 'top-right', 'BOTTOM' = 'bottom', 'BOTTOM-CENTER' = 'bottom-center', 'BOTTOM-LEFT' = 'bottom-left', 'BOTTOM-RIGHT' = 'bottom-right', 'LEFT' = 'left', 'RIGHT' = 'right', } ``` **anchor 使用示例(2D shape)** ```javascript // 气泡底部对齐到坐标位置,常用于地图标注场景 const bubbleLayer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' }, }) .shape('circle') .size(30) .color('#5B8FF9') .style({ anchor: 'bottom', }); // anchor 支持数据映射 const layer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' }, }) .shape('circle') .size(20) .color('#5B8FF9') .style({ anchor: { field: 'type', value: ['center', 'bottom', 'top'], }, }); ``` #### font css fontFamily。 ```js const font = 'sans-serif'; const font2 = 'Times New Roman'; ``` ### simple `shape` 为简单点图形(精灵)。 - [simple](/zh/api/point_layer/shape#shapesimple) | style | 类型 | 描述 | 默认值 | | ------------- | ------------------ | ------------ | -------- | | stroke | `string` | 图形边框颜色 | `#fff` | | strokeWidth | `number` | 图形边框颜色 | `0` | | strokeOpacity | `number` | 图形边框宽度 | `1` | | offsets | `[number, number]` | 点偏移 | `[0, 0]` | ### icon `shape` 为图标类型。 - [icon](/zh/api/point_layer/shape#shapeiconname-string) | style | 类型 | 描述 | 数据映射 | 默认值 | | ------------- | ------------------ | -------------------------------------------------------------------------- | -------- | -------- | | offsets | `[number, number]` | 点偏移 | 否 | `[0, 0]` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | | rotation | `number` | 旋转角度 | 是 | `0` | | allowOverlap | `boolean` | 图标是否允许压盖,`false` 时开启碰撞避让自动隐藏重叠图标 | 否 | `true` | | padding | `[number, number]` | 碰撞检测包围盒的额外边距 `[水平, 垂直]`,仅在 `allowOverlap: false` 时生效 | 否 | `[0, 0]` | #### rotation 图标的旋转角度。 ```js const imageLayer = new PointLayer({ layerType: 'fillImage' }) .source(data) .shape('wind', (wind) => { if (wind === 'up') { return 'arrBlue'; } return 'arrRed'; }) .size(15) .style({ rotation: 0, }); ``` #### allowOverlap 控制图标在屏幕上是否允许相互压盖。设置为 `false` 时,L7 会在每次地图缩放或平移后对所有图标执行碰撞检测,自动隐藏与已放置图标重叠的图标,效果与 `textAllowOverlap` 一致。 ```js const imageLayer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' } }) .shape('icon') .size(15) .style({ allowOverlap: false, // 开启碰撞避让 padding: [4, 4], // 图标之间保留 4px 间距 }); ``` ### radar `shape` 为雷达图。 - [radar](/zh/api/point_layer/shape#shaperadar) | style | 类型 | 描述 | 默认值 | | ----- | -------- | ---------------- | ------ | | speed | `number` | 雷达图旋转的速度 | `1` | ## animate 点图层在开启 `animate` 方法后根据点是 `2D` 点还是 `3D` 点支持两种不同的动画:水波点和生长动画。 点图层在开启 `animate` 方法后会得到特殊的水波图形。图层由一圈圈向外扩散的圆环构成。 ### 水波点 #### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` #### IAnimateOption ```javascript interface IAnimateOption { enable: boolean; speed: number; rings: number; } ``` ### 生长动画 #### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript animate(true) animate(false) animate(animateOptions) interface IAnimateOptions: { enable: boolean; speed?: number = 0.01; repeat?: number = 1; } ``` ``` #### IAnimateOptions `animate` 方法的参数: - `enable` 是否开启动画,布尔值,默认为 `false`。 - `speed` 生长速度,数值,默认为 `0.01`。 - `repeat` 生长动画的播放次数,数值,默认为 `1`。 ``` ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### PolygonLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/polygonlayer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/polygonlayer.md - Description: PolygonLayer --- title: "PolygonLayer" description: "PolygonLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/polygonlayer/" --- ## 简介 面图层用于绘制 2D 多边形以及沿 Z 轴拉伸后的 3D 图形,支持 GeoJSON Polygon / MultiPolygon 数据。 ```javascript import { PolygonLayer } from '@antv/l7'; const layer = new PolygonLayer() .source({ type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [104.4140625, 35.460669951495305], [98.7890625, 24.206889622398023], [111.796875, 27.371767300523047], [104.4140625, 35.460669951495305], ], ], }, }, ], }) .shape('fill') .color('#f00') .style({ opacity: 0.6, }); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## source 几何体图层数据推荐使用 GeoJSON 格式的数据。 - [GeoJSON](/zh/api/source/geojson/#point) ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 const data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [104.4140625, 35.460669951495305], [98.7890625, 24.206889622398023], [111.796875, 27.371767300523047], [104.4140625, 35.460669951495305], ], ], }, }, ], }; const layer = new PolygonLayer().source(data); ``` ## shape `shape` 方法用于指定面图层绘制图形的类型,如填充图,填充线,挤出集合体等。 ### shape('fill') `shape` 为 `fill` 几何图层用于绘制平面的几何图形。 ```js layer.shape('fill'); ``` ### shape('extrude') `shape` 为 `extrude` 几何图层用于绘制 3D 的几何体。 ```js layer.shape('extrude'); ``` ### extrusion extrude 图层的升级版, 支持 extrusionBase(基础高度)数据映射 ```js layer.shape('extrusion'); ``` ### shape('water') `shape` 为 `water` 几何图层用于绘制平面水体。 ```js layer.shape('water'); ``` ### shape('ocean') `shape` 为 `ocean` 几何图层用于绘制平面海洋水体。 ```js layer.shape('ocean'); ``` ### shape('line') `shape` 为 `line` 几何图层用于绘制线。 ```js layer.shape('line'); ``` ### shape('point_fill') `shape` 为 `point_fill` 几何图层用于绘制填充点。 ```js layer.shape('point_fill'); ``` ### shape('point_image') `shape` 为 `point_image` 几何图层用于绘制点图标。 ```js layer.shape('point_image'); ``` ### shape('point_extrude') `shape` 为 `point_extrude` 几何图层用于绘制柱子。 ```js layer.shape('point_extrude'); ``` ### shape('text') `shape` 为 `text` 几何图层用于绘制文字。 ```js layer.shape('text'); ``` ## color `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` ## size `size` 方法用于设置 Polygon 的高度 ### IPointSize: number |[number, number] | [number, number, number] - size 类型为 number 则表示 Polygon 的高度 ```javascript pointLayer.size(1); ``` ### size(width: IPointSize) 面图层可以直接设置半径。图层中所有的点使用一个高度。 ```js layer.size(2); ``` ### size(field: string) 面图层的高度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, r: 2, }, ]); layer.size('r'); ``` ### size(field: string, domain: IPointSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => IPointSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为面图层实际高度。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` ## scale `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` ## style `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | ### fill `shape` 为平面填充几何体。 - [fill](/zh/api/polygon_layer/shape#shapefill) | style | 类型 | 描述 | 默认值 | | ------------- | ---------------- | -------- | ------ | | raisingHeight | `number` | 抬升高度 | `0` | | opacityLinear | `IOpacityLinear` | 透明渐变 | `/` | #### opacityLinear ```js type IDir = 'in' | 'out'; interface IOpacityLinear { enable: false; dir: IDir; } ``` ### extrude `shape` 为挤出几何体。 - [extrude](/zh/api/polygon_layer/shape#shapeextrude) | style | 类型 | 描述 | 默认值 | | ------------- | --------- | -------------------------- | ------- | | raisingHeight | `number` | 抬升高度 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | `false` | | topsurface | `boolean` | 顶部是否显示 | `true` | | sidesurface | `boolean` | 侧面是否显示 | `true` | | sourceColor | `IColor` | 侧面底部颜色 | `/` | | targetColor | `IColor` | 侧面顶部颜色 | `/` | ### extrusion `shape` 为挤出几何体。 - [extrusion](/zh/api/polygon_layer/shape#extrusion) | style | 类型 | 描述 | 是否支持数据映射 | 默认值 | | ------------- | -------- | ---------------- | ---------------- | ------ | | extrusionBase | `number` | 基础高度,单位米 | 支持 | `0` | #### linear 几何体图层支持配置渐变效果(sourceColor、targetColor),在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 ### water `shape` 为水体表面几何体。 - [water](/zh/api/polygon_layer/shape#shapewater) | style | 类型 | 描述 | 默认值 | | ------------ | -------- | -------- | ------ | | speed | `number` | 水波速度 | `0.5` | | waterTexture | `string` | 水面贴图 | `0` | `waterTexture` 默认值为 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*EojwT4VzSiYAAAAAAAAAAAAAARQnAQ' ### ocean `shape` 为海洋表面几何体。 - [ocean](/zh/api/polygon_layer/shape#shapeocean) | style | 类型 | 描述 | 默认值 | | ----------- | -------- | -------- | --------- | | watercolor | `IColor` | 水面颜色 | `#6D99A8` | | watercolor2 | `IColor` | 水面颜色 | `#0F121C` | ### other 几何体图层支持的其他 `shape` 都有对应的图层,可以参考对应图层的样式参数。 ## animate 几何体图层在 `shape` 为 `water` 或 `ocean` 的时候会得到流动的水面,此时我们需要使用 `animate` 方法开启动画。 ### animate(boolean) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### RasterLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/raster_layer/raster/ - Markdown source: https://l7.antv.antgroup.com/zh/api/raster_layer/raster.md - Description: RasterLayer --- title: "RasterLayer" description: "RasterLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/raster_layer/raster/" --- ## 简介 `RasterLayer` 图层主要实现栅格数据的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图、植被分布图、夜光图等。L7 支持三种栅格可视化模式: | 模式 | shape 值 | 说明 | | ----------- | ----------- | ---------------------------------------------------- | | Raster Data | `raster` | 单波段,根据栅格数据值映射为颜色 | | Raster RGB | `rasterRgb` | 多波段,不同波段映射为 R/G/B 三通道展示 | | Raster NDI | `rasterNdi` | 多波段,提供两个波段进行归一化指数计算 `(b-a)/(b+a)` | ```javascript import { RasterLayer } from '@antv/l7'; // Raster Data 模式示例 const layer = new RasterLayer() .source(rasterData, { parser: { type: 'raster', width: 256, height: 256, extent: [73, 3, 136, 54], }, }) .style({ rampColors: { colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'], positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], }, }); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## Raster Data ## 简介 单波段栅格数据渲染、根据栅格数据进行可视化着色 ## source Raster data 数据栅格的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图、植被分布图和夜光图。 - data 数据 - option 配置项 - parser 数据解析参数 ### data data 解析后的数据,为数组 ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` 以 geotiff 为例需要先将数据解析出来,作为 data 输入给 source ```tsx import * as GeoTIFF from 'geotiff'; async function getTiffData() { async function getTiffData() { const response = await fetch( 'https://gw.alipayobjects.com/zos/antvdemo/assets/light_clip/lightF182013.tiff', ); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { data: values[0], width, height, }; } } const tiffdata = await getTiffData(); layer.source(tiffdata.data, { parser: { type: 'raster', width: tiffdata.width, height: tiffdata.height, extent: [73.4821902409999979, 3.8150178409999995, 135.1066187319999869, 57.6300459959999998], }, }); ``` ### parser - type: raster - extent: 栅格的经纬度范围 [minlng, minlat,maxLng, maxLat] - width 数据宽度 - height 数据高度 根据栅格数据的经纬度范围,将其添加到地图上。 ```javascript layer.source(rasterData, { parser: { type: 'raster', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` ### 完整示例 [Raster ndi](../../../../examples/raster/data/#dem) ## style `style` 方法用于配制图层的样式, - 单通道 绘制结果由是单一的数值控制,如灰度图,数值对应的颜色可以通过表示配置 `rampColors` 色带控制。 ```js layer.style({ opacity: 0.5, }); ``` ### 配置 | style | 类型 | 描述 | 默认值 | | ----------- | ------------------ | ------------------------------------------- | ------------- | | opacity | `number` | 图形的透明度 | `1` | | clampLow | `boolean` | 设置为 `true`,低于 `domain` 的数据将不显示 | `false` | | clampHigh | `boolean` | 设置为 `true`,高于 `domain` 的数据将不显示 | `false` | | domain | `[number, number]` | 数据映射区间 | `[ 0, 8000 ]` | | noDataValue | `number` | 不会显示的值 | `-9999999` | | rampColors | `IRampColors` | 值域映射颜色的色带 | `/` | ### rampColors 颜色色带 - type 类型 支持 `linear','quantize','custom','cat' - colors 颜色数组 - positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值 ⚠️ 2.13 新增特性 #### cat 枚举类型色带 枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举 ```tsx { type:'cat', colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'], positions:[1,20,101,102,200], } ``` #### quantize 等间距分类色带 等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。 等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数 ```tsx rampColors: { type:'quantize', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'] } ``` #### linear 线性连续色带 linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1 ```tsx rampColors: { type:'linear', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions [0,200,1000,4000,8000] } ⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。 ``` #### custom 自定义分段色带 自定义分段色带区别等间距色带,用户自定义分段间隔。 自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions ```tsx rampColors: { type:'custom', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions: [0,200,1000,4000,8000,10000] } ``` ## Raster RGB ## 简介 `Raster RGB ` 波段组合可视化,不同波段映射到 R/G/B 通道可视化 ## source raster-rgb source 是将多波段数据合成 RGB数据进行展示,如对 LandSat8 数据我们可以按照 5,4,3 或者 4,3,2 波段进行RGB组合显示 - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `rgb` ```ts layer.source(bandsValues, { parser: { type: 'rgb', width: bandsValues.width, height: bandsValues.height, bands: [4, 3, 2], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number,number] 指定 R/G/B 通道对应的数据索引,data 数组长度需要大于等于 3 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4,3 波段这样要设置为 4,3, 2) - width 长度 `必选` - height 宽度 `必选` - countCut 颜色拉伸参数 `[number,number]` 数值为百分比,默认值 `[2,98]` `可选` ### 完整示例 [Raster RGB](../../../../examples/raster/rgb/#543) ## style ### opacity 透明度 ```js layer.style({ opacity: 0.5, }); ``` ## Raster NDI ## 简介 `Raster NDI` Normalized Difference Indices 归一化指数计算,提供另个波段,进行归一化计算 ## source raster-ndi(Normalized Difference Indices) source 是将多波段数据进行归一化指数计算,比如计算NDVI/NDWI 等指数, - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `ndi` ```ts layer.source(bandsValues, { parser: { type: 'ndi', width: bandsValues.width, height: bandsValues.height, bands: [4, 3], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number] 指定需要归一化的波段,data 数组长度需要大于等于 2 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4, 波段这样要设置为 4,3) - width 长度 `必选` - height 宽度 `必选` ### 完整示例 [Raster ndi](../../../../examples/raster/ndi/#ndbi) ## style `style` 方法用于配制图层的样式, - 单通道 绘制结果由是单一的数值控制,如灰度图,数值对应的颜色可以通过表示配置 `rampColors` 色带控制。 ```js layer.style({ opacity: 0.5, }); ``` ### 配置 | style | 类型 | 描述 | 默认值 | | ----------- | ------------------ | ------------------------------------------- | ------------- | | opacity | `number` | 图形的透明度 | `1` | | clampLow | `boolean` | 设置为 `true`,低于 `domain` 的数据将不显示 | `false` | | clampHigh | `boolean` | 设置为 `true`,高于 `domain` 的数据将不显示 | `false` | | domain | `[number, number]` | 数据映射区间 | `[ 0, 8000 ]` | | noDataValue | `number` | 不会显示的值 | `-9999999` | | rampColors | `IRampColors` | 值域映射颜色的色带 | `/` | ### rampColors 颜色色带 - type 类型 支持 `linear','quantize','custom','cat' - colors 颜色数组 - positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值 ⚠️ 2.13 新增特性 #### cat 枚举类型色带 枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举 ```tsx { type:'cat', colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'], positions:[1,20,101,102,200], } ``` #### quantize 等间距分类色带 等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。 等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数 ```tsx rampColors: { type:'quantize', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'] } ``` #### linear 线性连续色带 linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1 ```tsx rampColors: { type:'linear', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions [0,200,1000,4000,8000] } ⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。 ``` #### custom 自定义分段色带 自定义分段色带区别等间距色带,用户自定义分段间隔。 自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions ```tsx rampColors: { type:'custom', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions: [0,200,1000,4000,8000,10000] } ``` ## 图层通用方法 ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### 场景 Scene - Canonical page: https://l7.antv.antgroup.com/zh/api/scene/ - Markdown source: https://l7.antv.antgroup.com/zh/api/scene.md - Description: 地图场景初始 --- title: "场景 Scene" description: "地图场景初始" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/scene/" --- ## 简介 场景对象 `scene` 是包含地图、地图控件、组件、加载资源的全局对象,通过 `scene` 场景对象,我们可以获取到操作地图需要的所有内容。 ## options ### id _string | HTMLElement_ **必选** 需传入 dom 容器或者容器 id。 ### map MapInstance **必选** 可以通过 scene map 属性获取 map 实例。 ```javascript const map = scene.map; ``` 为了统一不同底图之前的接口差异 `L7` 在 `Scene` 层对 `map` 的方法做了统一,因此一些地图的操作方法可以通过 `Scene` 调用,这样,切换不同底图时可以保证表现一致。 示例代码 ```javascript const scene = new L7.Scene({ id: 'map', map: new L7.GaodeMap({ style: 'dark', center: [110.770672, 34.159869], pitch: 45, }), }); ``` ### logoPosition _string_ **可选** _default: 'bottomleft'_ `L7` 默认提供的 `Logo` 可以配置显示位置,默认在左下角。 - bottomright - topright - bottomleft - topleft - topcenter - bottomcenter - leftcenter - rightcenter ### logoVisible logo 是否可见 _boolean_ **可选** _default: true_ 配置 `L7` 的 `Logo` 是否显示,默认显示。 ### antialias 是否开启抗锯齿 _boolean_ **可选** _default: true_ 是否开启抗锯齿。 ### stencil 是否开启裁剪 _boolean_ **可选** _default: true_ 是否开启裁剪(stencil)。图层 `Mask` 掩模能力以及矢量瓦片需要开启该配置。 🌟 从 v2.7.2 版本开始支持。 ### preserveDrawingBuffer _boolean_ **可选** _default: false_ 是否保留缓冲区数据。设置为 `true` 时可通过 `canvas.toDataURL()` 导出地图图片。 ### renderer 渲染器 _'regl' | 'device'_ **可选** _default: 'device'_ 指定渲染器类型。`regl` 为旧版渲染器,`device` 为新版渲染器(基于 `@antv/g-device-api`),默认使用 `device` 渲染器。 ```javascript const scene = new Scene({ id: 'map', map: new Map({}), renderer: 'device', // 或 'regl' }); ``` ### animate 是否启用动画 _boolean_ **可选** _default: undefined_ 是否启用动画渲染。 ### debug 是否开启调试 _boolean_ **可选** _default: false_ 是否开启调试模式,开启后会输出调试信息。 ### pickBufferScale 选取缓冲区缩放比 _number_ **可选** _default: 1.0_ 设置像素选取(picking)缓冲区的缩放比。 ### fitBoundsOptions 适配边界选项 _object_ **可选** 当调用 `fitBounds` 方法时默认的选项配置,包含 `animate` 等参数。 ## Layer 方法 ### addLayer(layer): void 增加图层对象 把图层添加到 `Scene` 场景中。 参数 : - `layer` 图层对象 ```javascript scene.addLayer(layer); ``` ### getLayer(id: string): ILayer 获取对应的图层对象 获取对应的图层。 ```javascript scene.getLayer('layerID'); ``` ### getLayers(): ILayer[] 获取所有的地图图层 获取所有的地图图层。 ```javascript scene.getLayers(); ``` ### getLayerByName(name: string): ILayer 根据图层名称获取图层 根据图层名称获取图层。 - `name` 图层在初始化的时候配置图层的 `name`。 ```javascript scene.getLayerByName(name); ``` ### removeLayer(layer: ILayer): void 移除 layer 图层 移除 `layer` 图层。 ```javascript scene.removeLayer(layer); ``` 🌟 移除的同时会将图层进行销毁。 ### removeAllLayer(): Promise\ 移除所有的图层对象 移除所有的图层对象。 ```javascript await scene.removeAllLayer(); ``` 🌟 移除的同时会将图层进行销毁。 ### render(): void 手动触发渲染 手动触发场景重新渲染。 ```javascript scene.render(); ``` ### setEnableRender(flag: boolean): void 设置是否启用渲染 控制是否允许图层渲染更新。当设置为 `false` 时,图层的渲染将被暂停。 ```javascript scene.setEnableRender(false); // 暂停渲染 scene.setEnableRender(true); // 恢复渲染 ``` ### getPickedLayer(): string 获取当前拾取的图层 获取当前被鼠标拾取(hover/click)的图层 ID。 ```javascript const layerId = scene.getPickedLayer(); ``` ## 控制组件方法 ### addControl(ctl: IControl): void 添加组件控件 添加组件控件。 - `crl` 用户创建的控件对象。 ```javascript scene.addControl(ctl); ``` ### removeControl(ctr: IControl): void 移除用户添加的组件控件 移除用户添加的组件控件。 - `ctl` 用户创建的控件对象。 ```javascript scene.removeControl(ctl); ``` ### getControlByName(name: string): IControl 根据控件的名称来获取控件 根据控件的名称来获取控件。 ```javascript const zoomControl = new Zoom({ // zoom 控件 name: 'z1', // 用户传入的控件名称(也可以不传入,该控件默认名称为 zoom) position: 'topright', }); scene.getControlByName('z1'); ``` ## 气泡方法 ### addPopup(popup: Popup): void 添加气泡 往场景中添加气泡对象,气泡用于展示用户自定义信息。 ```javascript scene.addPopup(popup); ``` ### removePopup(popup: Popup): void 移除气泡 往场景中移除气泡对象 ```javascript scene.removePopup(popup); ``` ## 标记方法 ### addMarker(maker: IMarker): void 添加标记 往场景中添加标记对象,`Marker` 实例是用户自由控制的 `DOM`。 - `maker` 用户创建的 `Marker` 实例。 ```javascript const marker = new Marker({ element: el, }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); scene.addMarker(marker); ``` ### addMarkerLayer(layer: IMarkerLayer): void 添加 Marker 统一管理图层 当用户需要添加许多个 `Marker` 实例时,为了方便管理可以使用 `MarkerLayer` 对象统一管理。 - `layer` 标记图层对象。 ```javascript const markerLayer = new MarkerLayer(); scene.addMarkerLayer(markerLayer); ``` ### removeMarkerLayer(layer: IMarkerLayer): void 移除标签图层 移除标签图层。 - `layer` 标记图层对象。 ```javascript scene.removeMarkerLayer(markerLayer); ``` ### removeAllMarkers(): void 移除场景中所有的标签对象 移除场景中所有的标签对象。 ```javascript scene.removeAllMarkers(); ``` ### removeAllMakers(): void ⚠️ 已废弃 > ⚠️ 此方法已废弃,请使用 `removeAllMarkers()` 替代。 ## 静态方法 静态方法通过 Scene 类去调用,不是 scene 实例 ### addProtocol 添加自定义数据协议,设置一个自定义加载瓦片函数,当使用以自定义 URL 模式开头的数据时,该函数将被调用。 - protocol 协议名称 - handler 数据处理回调函数 - requestParameters: RequestParameters, - url 瓦片 URL,携带瓦片行列号 x,y,z - callback: ResponseCallback) => Cancelable - Cancelable: { cancel: () => void; }; #### 自定义函数 ```ts Scene.addProtocol('custom', (params, callback) => { fetch(`https://${params.url.split('://')[1]}`) .then((t) => { if (t.status == 200) { t.arrayBuffer().then((arr) => { callback(null, arr, null, null); }); } else { callback(new Error(`Tile fetch error: ${t.statusText}`)); } }) .catch((e) => { callback(new Error(e)); }); return { cancel: () => {} }; }); // the following is an example of a way to return an error when trying to load a tile Scene.addProtocol('custom2', (params, callback) => { callback(new Error('someErrorMessage')); return { cancel: () => {} }; }); ``` #### 加载 PMTiles ```ts import * as pmtiles from 'pmtiles'; const protocol = new pmtiles.Protocol(); const scene = new Scene({ id: 'map', map: new Map({ center: [11.2438, 43.7799], zoom: 12, }), }); scene.addProtocol('pmtiles', protocol.tile); const source = new Source( 'pmtiles://https://mdn.alipayobjects.com/afts/file/A*HYvHSZ-wQmIAAAAAAAAAAAAADrd2AQ/protomaps(vector)ODbL_firenze.bin', { parser: { type: 'mvt', tileSize: 256, maxZoom: 14, extent: [-180, -85.051129, 179, 85.051129], }, }, ); ``` ### removeProtocol 删除之前添加的协议 - name: 协议名称 ```ts scene.removeProtocol('pmtiles', protocol.tile); ``` ## 地图方法 ### getZoom(): number 获取缩放等级 获取当前缩放等级。 ```javascript scene.getZoom(); ``` ### getCenter(): ILngLat 获取地图中心 获取地图中心点 ```javascript interface ILngLat { lng: number; lat: number; } scene.getCenter(); ``` ### getSize(): [number, number] 获取地图容器大小 获取地图容器大小,width、height。 ```javascript scene.getSize(); ``` ### getPitch(): number 获取地图倾角 获取地图俯仰角。 ```javascript scene.getPitch(); ``` ### getContainer(): HTMLElement | null 获取地图容器 获取地图容器。 ```javascript scene.getContainer(); ``` ### setMapStyle(style: string): void 设置地图样式 参数 `style` 参数是字符串,可以选择内置的地图样式 具体样式格式和各底图设置方法一致。 `L7` 内置了三种地图样式,`AMAP` 和 `MapBox` 都适用。 - light - dark - normal 设置地图底图样式的方法。 ```javascript // 快捷名称设置 scene.setMapStyle('light'); // mapbox 主题设置 scene.setMapStyle('mapbox://styles/mapbox/streets-v11'); // AMap scene.setMapStyle('amap://styles/2a09079c3daac9420ee53b67307a8006?isPublic=true'); ``` ### setCenter(center: ICenter, option?: ICameraOptions): void 设置地图中心点 设置地图中心点坐标。`L7` 提供了 `setCenter` 方法,允许用户动态的设置地图的中心点位,同时允许通过可选的 `options` 属性设置偏移。 ```js type ICenter = [number, number]; interface ICameraOptions { padding: | number | [number, number, number, number] | { top?: number, bottom?: number, right?: number, left?: number, }; } scene.setCenter([lng, lat]); scene.setCenter([lng, lat], { padding: { top: 100, }, }); ``` 🌟 `padding` 参数支持如下的三种传值方式,数值的单位是 `px`,表示地图中心点距离容器边缘的偏移距离。 ```javascript export interface ICameraOptions { padding: | number | [number, number, number, number] | { top?: number, bottom?: number, right?: number, left?: number, }; } ``` [在线案例](/zh/examples/point/bubble/point/) ### setZoomAndCenter(zoom: number, center: ICenter): void 设置地图缩放等级和中心点 设置地图等级和中心。 ```javascript type ICenter = [number, number]; scene.setZoomAndCenter(zoom, center); ``` ### setZoom(zoom: number): void 设置地图缩放等级 设置地图缩放等级 ```javascript scene.setZoom(10); ``` ### setRotation(rotation: number): void 设置地图旋转 设置地图顺时针旋转角度,旋转原点为地图容器中心点,取值范围 [0-360]。 ```javascript scene.setRotation(rotation); ``` ### zoomIn(); void 地图放大一级 地图放大一级。 ```javascript scene.zoomIn(); ``` ### zoomOut(): void 地图缩小一级 地图缩小一级。 ```javascript scene.zoomOut(); ``` ### panTo(lnglat: ILngLat): void 地图移动 地图平移到指定的经纬度位置。 ```javascript type ILngLat = [number, number]; scene.panTo(LngLat); ``` ### panBy(x: number, y: number): void 地图平移 以像素为单位沿 X 方向和 Y 方向移动地图。 - `x` 水平方向移动像素 向右为正方向。 - `y` 垂直方向移动像素 向下为正方向。 ```javascript scene.panBy(x, y); ``` ### setPitch(pitch: number): void 设置地图倾角 设置地图仰俯角度。 ```javascript scene.setPitch(pitch); ``` ### setMapStatus(statusOption: IStatusOptions): void 设置地图状态 用来设置地图的一些交互配置。 ```javascript interface IStatusOptions { showIndoorMap: boolean; resizeEnable: boolean; dragEnable: boolean; keyboardEnable: boolean; doubleClickZoom: boolean; zoomEnable: boolean; rotateEnable: boolean; } scene.setMapStatus({ dragEnable: false }); ``` ### fitBounds(bound: IBounds, options?: IOptions): void 设置地图缩放范围 地图缩放到某个范围内。 - `bound` 表示经纬度范围 [[minlng,minlat],[maxlng,maxlat]]。 - `options` 用户传入,覆盖 `animate` 直接配置,覆盖 `Scene` 传入的配置项。 ```javascript type IBounds = [[number, number], [number, number]]; interface IOptions { [key]: any; animate: boolean; } scene.fitBounds([ [112, 32], [114, 35], ]); ``` ### containerToLngLat(point: IPoint): ILngLat 画布坐标转经纬度 将画布坐标转经纬度坐标 ```javascript type IPoint = [number, number]; interface ILngLat { lng: number; lat: number; } scene.containerToLngLat([10, 10]); ``` ### lngLatToContainer(lnglat: ILngLat): IPoint 经纬度转画布坐标 经纬度坐标转画布坐标。 ```javascript type ILngLat = [number, number]; interface IPoint { x: number; y: number; } scene.lngLatToContainer([120, 10]); ``` ### pixelToLngLat(pixel: IPoint): ILngLat 像素坐标转经纬度 地图像素坐标转经纬度坐标,像素坐标地图上某点距离容器左上角的位置。 ```javascript type IPoint = [number, number]; interface ILngLat { lng: number; lat: number; } scene.pixelToLngLat([10, 10]); ``` ### lngLatToPixel(lnglat: ILngLat): IPoint 经纬度转像素坐标 经纬度坐标转像素坐标。 ```javascript type ILngLat = [number, number]; interface IPoint { x: number; y: number; } scene.lngLatToPixel([120, 10]); ``` ### exportMap(type?: IImage): string 导出 导出地图,目前仅支持导出可视化层,不支持底图导出。 ```javascript type IImage = 'png' | 'jpg'; scene.exportMap('png'); ``` ### exportPng(type?: 'png' | 'jpg'): string 导出图片 `exportMap` 的别名方法,导出地图为图片。 ```javascript scene.exportPng('png'); // 等同于 scene.exportMap('png') scene.exportPng('jpg'); // 等同于 scene.exportMap('jpg') ``` ### setBgColor(color: string): void 设置背景色 设置场景背景颜色。 ```javascript scene.setBgColor('#000000'); ``` ### registerPostProcessingPass(constructor: any, name: string): void 注册后处理通道 注册后处理特效通道,用于实现如泛光(Bloom)、色彩校正等后处理效果。 ```javascript import { Scene, PostProcessingPass } from '@antv/l7'; scene.registerPostProcessingPass(PostProcessingPass, 'bloom'); ``` ### enableShaderPick(): void 启用着色器拾取 启用着色器拾取模式。 ```javascript scene.enableShaderPick(); ``` ### disableShaderPick(): void 禁用着色器拾取 禁用着色器拾取模式。 ```javascript scene.disableShaderPick(); ``` ### diasbleShaderPick(): void ⚠️ 已废弃 > ⚠️ 此方法名拼写错误已废弃,请使用 `disableShaderPick()` 替代。 ### enableBoxSelect(once?: boolean): void 启用框选 启用框选功能,允许用户通过拖拽矩形框来选择区域。`once` 参数为 `true` 时表示只触发一次框选后自动关闭。 ```javascript scene.enableBoxSelect(); // 持续框选 scene.enableBoxSelect(true); // 框选一次后自动关闭 ``` 框选事件可通过 `boxselect` 事件监听: ```javascript scene.on('boxselect', (e) => { console.log(e.bounds); // 框选的经纬度范围 }); ``` ### disableBoxSelect(): void 禁用框选 禁用框选功能。 ```javascript scene.disableBoxSelect(); ``` ### boxSelectEnable: boolean 框选状态 属性,表示当前框选是否启用。 ### startAnimate(): void 启动动画 启动持续渲染动画。默认情况下 L7 按需渲染,调用此方法可开启实时渲染循环,在需要持续动画或使用 SpectorJS 调试时非常有用。 ```javascript scene.startAnimate(); ``` ### stopAnimate(): void 停止动画 停止实时渲染动画,恢复按需渲染模式。 ```javascript scene.stopAnimate(); ``` ### getPointSizeRange(): Float32Array 获取点精灵大小范围 获取当前设备支持绘制的 `WebGL` 点精灵的大小范围。 ```javascript const range = scene.getPointSizeRange(); // range[0] 最小值, range[1] 最大值 ``` ### getMapService(): IMapService 获取地图服务 获取底层地图服务实例,可用于直接调用底图特有方法。 ```javascript const mapService = scene.getMapService(); ``` ### getMapContainer(): HTMLElement 获取地图容器 获取地图的主容器 DOM 元素。 ```javascript const container = scene.getMapContainer(); ``` ### getMapCanvasContainer(): HTMLElement 获取地图画布容器 获取地图画布容器的 DOM 元素。 ```javascript const canvasContainer = scene.getMapCanvasContainer(); ``` ### getServiceContainer(): IContainer 获取服务容器 获取依赖注入容器,可用于获取注册的服务实例。 ```javascript const container = scene.getServiceContainer(); ``` ### getType(): string 获取地图类型 获取当前使用的地图类型。 ```javascript const mapType = scene.getType(); // 如 'gaode', 'mapbox', 'map' 等 ``` ### getMinZoom(): number 获取最小缩放等级 获取地图支持的最小缩放等级。 ```javascript const minZoom = scene.getMinZoom(); ``` ### getMaxZoom(): number 获取最大缩放等级 获取地图支持的最大缩放等级。 ```javascript const maxZoom = scene.getMaxZoom(); ``` ### addIconFontGlyphs(fontFamily: string, glyphs: string[]): void 添加 IconFont 字形 为指定字体族添加字形数据,用于 SDF 文本渲染。 - `fontFamily` 字体族名称 - `glyphs` 字形数据数组 ```javascript scene.addIconFontGlyphs('iconfont', ['glyph1', 'glyph2']); ``` ### destroy(): void 场景销毁 `scene` 销毁方法,离开页面,不需要使用地图的时候调用,调用后 `scene` 中的资源和都会被销毁。 ```javascript scene.destroy(); ``` ## iconfont 映射支持 ### addIconFont(name: string, unicode: string): void 增加映射支持 支持对用户传入的数据进行 `unicode` 的映射,在内部维护一组名称和对应 `key` 的键值对。 ```javascript scene.addIconFont('icon1', ''); scene.addIconFont('icon2', ''); scene.addFontFace(fontFamily, fontPath); const pointIconFontLayer = new PointLayer({}) .source( [ { j: 140, w: 34, m: 'icon1', }, { j: 140, w: 36, m: 'icon2', }, ], { parser: { type: 'json', x: 'j', y: 'w', }, }, ) .shape('m', 'text') .size(12) .color('w', ['#f00', '#f00', '#0f0']) .style({ fontFamily, iconfont: true, textAllowOverlap: true, }); ``` ### addIconFonts(option: IOption): void 同时传入多组 name - unicode 的键值对 同时传入多组 `name - unicode` 的键值对。 ```javascript type IKeyValue = [name: string, unicode: string]; type IOption = Array; scene.addIconFonts([ ['icon1', ''], ['icon2', ''], ]); ``` ## 全局资源 ### addImage(id: string, img: IImage): void 添加全局资源 在 `scene` 全局中添加 `L7` 的图层对象可以使用的图片资源在。 ```javascript type IImage = HTMLImageElement | string | File; scene.addImage( '02','https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg'); ``` [示例地址](/zh/examples/gallery/animate/animate-path-texture/) ### hasImage(id: string): boolean 判断全局图片资源 判断是否已经在全局添加过相应的图片资源。 ```javascript scene.hasImage('imageID'); ``` ### removeImage(id: string): void 全局删除图片资源 从全局删除对应的图片资源。 ```javascript scene.removeImage('imageID'); ``` ### addFontFace(fontFamily: string, fontPath: string): void 添加字体文件 添加 `iconfont` 字体文件。 - `fontFamily` 用户为自己定义的字体名称 - `fontPath` 导入的文件地址 ```javascript let fontFamily = 'iconfont'; let fontPath = '//at.alicdn.com/t/font_2534097_iiet9d3nekn.woff2?t=1620444089776'; scene.addFontFace(fontFamily, fontPath); ``` ## 属性 ### loaded: boolean 场景是否加载完成。 ```javascript if (scene.loaded) { console.log('场景已加载'); } ``` ### map: IMapInstance 获取底层地图实例,可用于调用底图特有的 API。 ```javascript const mapInstance = scene.map; ``` ## 事件 ### on(eventName: string, handler: function): void 在 `scene` 上绑定事件监听。 - `eventName` 事件名。 - `handler` 事件回调函数。 ### off(eventName: string, handler: function): void 移除在 `scene` 上绑定的事件监听。 - `eventName` 事件名。 - `handler` 事件回调函数。 ### once(eventName: string, handler: function): void 在 `scene` 上绑定一次性事件监听,触发一次后自动移除。 - `eventName` 事件名。 - `handler` 事件回调函数。 ### 场景事件 `scene` 会触发一些常见的场景事件,用户在需要的时候可以进行监听。 #### loaded `scene` 初始化完成事件,我们经常在 `scene` 初始化完成后添加 `Layer`。 ```javascript scene.on('loaded', () => { scene.addLayer(layer); }); ``` #### maploaded 底层地图加载完成事件。 ```javascript scene.on('maploaded', () => { console.log('底图加载完成'); }); ``` #### fontloaded 字体加载完成事件。 ```javascript scene.on('fontloaded', () => { console.log('字体加载完成'); }); ``` #### resize 地图容器变化事件 ```javascript scene.on('resize', () => {}); // 地图容器大小改变事件 ``` #### destroy 场景销毁事件。 ```javascript scene.on('destroy', () => { console.log('场景已销毁'); }); ``` #### startAnimate 默认 L7 按需重绘,通过启动动画开启实时渲染,便于 SpectorJS 插件捕捉帧渲染。 #### stopAnimate 调试时使用,停止实时渲染 ### 地图事件 ```javascript scene.on('loaded', () => {}); //地图加载完成触发 scene.on('mapmove', () => {}); // 地图平移时触发事件 scene.on('movestart', () => {}); // 地图平移开始时触发 scene.on('moveend', () => {}); // 地图移动结束后触发,包括平移,以及中心点变化的缩放。如地图有拖拽缓动效果,则在缓动结束后触发 scene.on('zoomchange', () => {}); // 地图缩放级别更改后触发 scene.on('zoomstart', () => {}); // 缩放开始时触发 scene.on('zoomend', () => {}); // 缩放停止时触发 ``` 其他地图事件可以查看相应底图的事件文档,地图事件也可以通过 `Scene.map` 进行设置。 [Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/#map.event) [高德](https://lbs.amap.com/api/javascript-api/reference/map) ### 鼠标事件 ```javascript scene.on('click', (ev) => {}); // 鼠标左键点击事件 scene.on('dblclick', (ev) => {}); // 鼠标左键双击事件 scene.on('mousemove', (ev) => {}); // 鼠标在地图上移动时触发 scene.on('mousewheel', (ev) => {}); // 鼠标滚轮开始缩放地图时触发 scene.on('mouseover', (ev) => {}); // 鼠标移入地图容器内时触发 scene.on('mouseout', (ev) => {}); // 鼠标移出地图容器时触发 scene.on('mouseup', (ev) => {}); // 鼠标在地图上单击抬起时触发 scene.on('mousedown', (ev) => {}); // 鼠标在地图上单击按下时触发 scene.on('contextmenu', (ev) => {}); // 鼠标右键单击事件 scene.on('dragstart', (ev) => {}); //开始拖拽地图时触发 scene.on('dragging', (ev) => {}); // 拖拽地图过程中触发 scene.on('dragend', (ev) => {}); //停止拖拽地图时触发。如地图有拖拽缓动效果,则在拽停止,缓动开始前触发 scene.on('webglcontextlost', () => {}); // webgl 上下文丢失 ``` ### 拖拽事件 ```javascript scene.on('dragstart', (ev) => {}); // 开始拖拽地图时触发 scene.on('dragging', (ev) => {}); // 拖拽地图过程中触发 scene.on('dragend', (ev) => {}); // 停止拖拽地图时触发。如地图有拖拽缓动效果,则在拖拽停止,缓动开始前触发 scene.on('dragcancel', (ev) => {}); // 拖拽取消时触发 ``` ### 框选事件 当调用 `scene.enableBoxSelect()` 后,框选操作会触发以下事件: ```javascript scene.on('boxselect', (ev) => { console.log(ev.bounds); // 框选的经纬度范围 [[minLng, minLat], [maxLng, maxLat]] }); scene.on('boxselectstart', (ev) => {}); // 框选开始 scene.on('boxselecting', (ev) => {}); // 框选中 scene.on('boxselectend', (ev) => {}); // 框选结束 ``` ## 实验参数 实验参数可能会废弃。 ### offsetCoordinate: boolean 高德地图适用,是否关闭偏移坐标系, 默认为 `true`。 ```js const scene = new Scene({ offsetCoordinate: true, }); ``` #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/source/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/source/" --- ## 简介 source 地理数据处理模块,主要包含数据解析(parser)和数据处理(transforms)。 ```js const source = new Source(data, option); ``` - data - option - cluster **boolean** 是否聚合 - clusterOptions 聚合配置项 - parser 数据解析配置 - transforms 数据处理配置 ## 兼容性 本次渐进式重构(阶段 0–6)保证**对外 API 完全向后兼容**,旧写法无需改动即可继续工作: - `new Source(data, cfg)` 与 `new Source(data)` 写法保持不变(`cfg` 与 `registry` 均可选)。 - `cluster: true` 配置静默走新 `ClusterManager` 直调路径,**无任何 warning**。 - `ISourceCFG` 旧字段(`cluster` / `clusterOptions` / `parser` / `transforms` / `autoRender`)全部保留。 - 事件 `'update' { type: 'inited' | 'update' }` 行为不变;新增 `'error'` 事件仅用于显式 surfacing 失败(无监听即静默)。 新增的 `Source.create` / `createSource` / `source.ready` / `source.stats()` / `source.dataVersion` 为可选的更优路径,旧代码可按需逐步迁移,非强制。 > `transforms` 配置项中 `{ type: 'cluster' }` 已弃用(运行时会 warn 一次,但仍可工作)。聚合请改用顶层 `cluster: true` 配置项,详见下方 [cluster](#cluster)。 ## data 不同 parser 类型对应不同 data 类型 - 瓦片图层 data 为 url 模板,支持 TMS、WMS、WMTS 数据服务 - 非瓦片图层 data 为数据对象 ## option `source` 通过 `option` 来描述或处理数据, 其中主要包括 `parser` 和 `transforms`。 ### parser parser 可以将不同类型的空间数据处理成统一数据格式。空间数据分为矢量数据、栅格数据和瓦片服务三大类: - 矢量数据 支持 [GeoJSON](/zh/api/source/geojson)、[CSV](/zh/api/source/csv)、[JSON](/zh/api/source/json) 类型 - 栅格数据 支持 [Raster](/zh/api/source/raster)、[Image](/zh/api/source/image) 类型 - 瓦片服务 支持 [MVT](/zh/api/source/mvt)、[RasterTile](/zh/api/source/raster_tile)、GeoJSON VT 类型 ```js type IParserType = | 'csv' | 'json' | 'geojson' | 'image' | 'raster' | 'rasterTile' | 'mvt' | 'geojsonvt'; interface IParser { type: IParserType; x?: string; y?: string; x1?: string; y1?: string; coordinates?: string; geometry?: string; [key: string]: any; } ``` #### geojson [geojson](https://www.yuque.com/antv/l7/dm2zll) 为默认数据格式,可以不设置 parser 参数 ```javascript layer.source(data); ``` ### transforms transforms 处理的是标准化后的数据,可进行数据转换、数据统计、网格布局、数据聚合等数据操作,处理完后返回的也是标准数据。标准化后的数据结构包括 coordinates 地理坐标字段,以及其他属性字段。 ```json [ { "coordinates": [[]], // 地理坐标字段 "_id": "122", // 标准化之后新增字段 "name": "test", "value": 1 // .... } ] ``` 目前 grid、hexagon 两种热力图支持使用数据处理方法 transforms 配置项 - type 数据处理类型 - transforms cfg 数据处理配置项 #### grid 生成方格网布局,根据数据字段统计,主要在网格热力图中使用 - type: 'grid' - size: 网格半径 - field: 数据统计字段 - method: 聚合方法,有 count、max、min、sum、mean 5 个统计维度 ```javascript layer.source(data, { transforms: [ { type: 'grid', size: 15000, field: 'v', method: 'sum', }, ], }); ``` #### hexagon 生成六边形网格布局,根据数据字段统计 - type: 'hexagon' - size: 网格半径 - field: 数据统计字段 - method: 聚合方法,有 count、max、min、sum、mean 5 个统计维度 #### join 数据连接,业务中跟多情况是地理数据和业务数据分开的两套数据,我们可与通过 join 方法将地理数据和业务数据进行关联。 **配置项** - type: join - sourceField: 需要连接的业务数据字段名称 - data: 需要连接的数据源,仅支持 json 格式 - targetField: 关联的地理数据字段名称 ```javascript // geoData 是地理数据 const geoData = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: { city: '北京', }, geometry: {}, }, ], }; // customData 属性数据或者业务数据 const customData = [ { name: '北京', value: 13, }, { name: '天津', value: 20, }, ]; // 通过 join 方法我们就可以将两个数据连接到一起 layer .source(geoData, { transforms: [ { type: 'join', sourceField: 'name', //customData 对应字段名 targetField: 'city', // geoData 对应字段名,绑定到的地理数据 data: customData, }, ], }) .color('value'); // 可以采用 customData 的 value 字段进行数据到颜色的映射 ``` #### map 对数据进行映射转换,可对每一个数据元素进行处理并返回新的数据元素。 **配置项** - type: 'map' - callback: `(feature: any) => any` 对每条数据进行处理的回调函数 ```javascript layer.source(data, { transforms: [ { type: 'map', callback: (feature) => { feature.value = feature.value * 2; return feature; }, }, ], }); ``` #### filter 对数据进行过滤,仅保留满足条件的数据元素。 **配置项** - type: 'filter' - callback: `(feature: any) => boolean` 过滤条件回调函数,返回 `true` 时保留该条数据 ```javascript layer.source(data, { transforms: [ { type: 'filter', callback: (feature) => { return feature.value > 10; // 仅保留 value 大于 10 的数据 }, }, ], }); ``` ### cluster - cluster: `boolean` `cluster` 表示是否对数据进行聚合操作, 目前只有点图层支持。 > 推荐使用 `cluster: true` 顶层配置项开启聚合。 > `transforms: [{ type: 'cluster' }]` 已弃用(会破坏 `source.data` 语义并 warn),仅为向后兼容保留。 ### clusterOption 可选 - radius: 聚合半径 **number** default 40 - minZoom: 最小聚合缩放等级 **number** default 0 - maxZoom: 最大聚合缩放等级 **number** default 16 [聚合图使用案例](/zh/examples/point/cluster/cluster/) ## 方法 ### setData(data, options?) 更新数据 更新 source 数据,会触发图层重新渲染。 - `data` 数据,同 source 初始化参数 - `options` 配置项,同 source 初始化参数 ```javascript const source = new Source(data, { parser: { type: 'json', x: 'lng', y: 'lat' } }); // 更新数据 source.setData(newData); ``` ### getFeatureById(id: number) 根据 ID 获取要素 根据 featureID 获取 feature 要素。 - `id` featureId,L7 内部编码的唯一要素 ID ```tsx const source = layer.getSource(); const feature = source.getFeatureById(1); ``` ### getFeatureId(field: string, value: any) 根据属性获取要素 ID 根据属性的 key、value 获取要素 L7 编码 featureId,确保该属性的 value 是唯一值,如存在多个返回第一个。 - `field` 属性字段 - `value` 对应的值 ```tsx const source = layer.getSource(); const featureId = source.getFeatureId('name', '张三'); ``` ### updateFeaturePropertiesById(id, properties) 更新要素属性 根据 ID 更新 source 的属性数据,会触发重新渲染。 - `id` featureId,L7 内部编码的唯一要素 ID - `properties` 需要更新属性数据,进行 merge 操作 ```tsx const source = layer.getSource(); layer.on('click', (e) => { source.updateFeaturePropertiesById(e.featureId, { name: Math.random() * 10, }); }); ``` ### getClusters(zoom: number) 获取聚合数据 聚合图使用,获取指定缩放等级下的聚合数据。 - `zoom` 缩放等级 ```javascript const clusters = source.getClusters(scene.getZoom()); ``` ### getClustersLeaves(cluster_id) 获取聚合节点原始数据 聚合图使用,获取聚合节点的原始数据。 - `id` 聚合节点的 cluster_id ```javascript layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ### updateClusterData(zoom: number) 更新聚合数据 更新聚合数据,在地图缩放后需要调用以刷新聚合结果。 - `zoom` 当前缩放等级 ```javascript scene.on('zoomchange', () => { source.updateClusterData(scene.getZoom()); }); ``` ### getSourceCfg() 获取 source 配置 获取 source 的初始化配置项。 ```javascript const cfg = source.getSourceCfg(); ``` ### getParserType() 获取解析器类型 获取当前 source 使用的数据解析器类型。 ```javascript const parserType = source.getParserType(); // 如 'geojson', 'json', 'csv', 'mvt' 等 ``` ### destroy() 销毁 source 销毁 source,释放相关资源。 ```javascript source.destroy(); ``` ### create(data, cfg?) 异步工厂方法 `Source.create` 是异步工厂方法,内部 `await` source 初始化(parse + cluster 初始化 + transforms)完成后返回。相比 `new Source(data, cfg)` 的 fire-and-forget 初始化,`create` 返回的实例 `data` 已就绪,可直接读取,消除 `source.data` 可能为 `undefined` 的竞态。 - `data` 数据,同 source 初始化参数 - `cfg` 配置项,同 source 初始化参数 - 返回 `Promise` ```javascript const source = await Source.create(data, { parser: { type: 'json', x: 'lng', y: 'lat' } }); // 此时 source.data 已解析完成,无 undefined 竞态 ``` ### createSource(data, cfg?, registry?) 同步工厂 `createSource` 与 `new Source` 行为等价的同步工厂函数,返回 source 实例(初始化仍为 fire-and-forget)。第三个可选参数 `registry` 可注入自定义 `ParserRegistry` 实例,按需子集注册 parser / transform 或做测试隔离。 - `data` 数据,同 source 初始化参数 - `cfg` 配置项,同 source 初始化参数 - `registry`(可选)自定义 parser / transform 注册表,默认使用内置 `defaultRegistry` ```javascript import { createSource } from '@antv/l7-source'; const source = createSource(data, { parser: { type: 'geojson' } }); ``` ### ready 只读属性 `source.ready` 是一个 `Promise`,resolve 时 source 初始化完成(`inited === true` 且数据已解析)。可在消费侧 `await source.ready` 消除 `source.data` 竞态。 ```javascript const source = new Source(data); await source.ready; // source.data 已就绪 ``` ### stats() 获取数据快照 返回 source 当前数据的只读快照,便于调试与大小监控。不影响 source 内部状态。 返回 `ISourceStats` 对象: - `rows: number` 已解析数据行数(`data.dataArray.length`) - `bbox: BBox` 数据范围 `[minLng, minLat, maxLng, maxLat]` - `parserType: string` 当前解析器类型(如 `'geojson'`、`'mvt'`) - `tileCount: number` 已加载瓦片数(非瓦片源或未触发视口更新时为 `0`) - `isTile: boolean` 是否为瓦片数据源 - `cluster: boolean` 是否开启聚合 - `dataVersion: number` 数据 generation(见下) ```javascript const stats = source.stats(); console.log(stats.rows, stats.parserType, stats.tileCount); ``` ### dataVersion 数据版本号 `dataVersion` 是单调递增的数据 generation 计数器,每次「数据可能变化」的操作 `+1`: - `setData`(全量数据替换)后 `+1` - `updateFeaturePropertiesById`(原地属性变更)后 `+1` - `updateClusterData`(zoom 驱动的聚合视图重算,原始数据未变)**不** bump - 构造期首次解析为 generation `0` 可用于判断数据是否已变化、避免重复处理。 ```javascript const v1 = source.dataVersion; source.setData(newData); const v2 = source.dataVersion; // v2 === v1 + 1 ``` ## Source 更新 如果数据发生改变,可以需要更新数据。 可以通过调用 `layer` 的 `setData` 方法实现数据的更新。 具体见 [Layer](/zh/api/base_layer/base/#setdata) ```javascript layer.setData(data); ``` ## 瓦片 source 属性 ### tileset 瓦片数据集,可以获取当前视野内的瓦片信息, 瓦片状态 ```ts const source = layer1.getSource(); const tileSet = source.tileset; ``` #### 属性 ##### isLoaded 瓦片是否加载完成 ##### currentTiles 当前瓦片对象 ##### currentZoom 当前瓦片层级;这里的曾经和map 的缩放层级不相等 #### 事件 ##### tiles-load-start 地图拖动,需要加载新的瓦片时触发 ```ts tileSet.on('tiles-load-start', () => { console.log('tile start'); }); ``` ##### tiles-load-finished 所有需要加载的瓦片资源加载完成后触发 ```ts tileSet.on('tiles-load-finished', () => { console.log('tile finished'); }); ``` ## 瓦片 source 方法 ### reloadAllTile 重新加载瓦片,会重新请求数据,适用与动态瓦片场景,如瓦片数据发生了更新,或者瓦片Join 的数据发生了更新 ```ts pure source.reloadAllTile(); ``` ### reloadTilebyId 重新加载特定瓦片的 参数 - z 缩放等级 - x 瓦片 x 坐标 - y 瓦片 y 坐标 ```ts pure source.reloadTileById(z, x, y); ``` ### reloadTileByExtent 根据经纬度范围更新瓦片 参数 - extent: 经纬范围 [minLng, minLat, maxLng, maxLat] - zoom: 缩放等级 ### reloadTileByLnglat 根据经纬度更新瓦片,经纬度坐标转换成瓦片坐标更新 - lng 经度 - lat 纬度 - zoom 缩放等级 ```tsx pure source.reloadTileByLnglat(112, 30, 10); ``` ### 数据类型 #### JSON [JSON 数据格式解析](/zh/api/source/json) #### csv [CSV 数据格式解析](/zh/api/source/csv) 栅格数据类型 #### image [Image 数据格式解析](/zh/api/source/image) ## 事件 Source 继承自 EventEmitter,支持 `on`/`off`/`once`/`emit` 等事件方法。 ### update 数据更新事件,在以下情况触发: - source 初始化完成后(`type: 'inited'`) - 调用 `setData` 或 `updateFeaturePropertiesById` 后(`type: 'update'`) ```javascript const source = layer.getSource(); source.on('update', (e) => { if (e.type === 'inited') { console.log('source 初始化完成'); } else if (e.type === 'update') { console.log('source 数据已更新'); } }); ``` ### error 数据初始化或更新失败事件。当 `setData` 触发的 re-parse / cluster 初始化 / transform 执行失败时触发,payload 为错误对象。使用 `setData` 时建议监听 `error` 事件以感知失败(旧版本失败会静默 hang,现为显式 surfacing)。 ```javascript const source = layer.getSource(); source.on('error', (err) => { console.error('source 数据更新失败', err); }); source.setData(newData); ``` > 注:`new Source(data, cfg)` 构造期 init 失败仍为 fire-and-forget(未捕获 rejection,保留旧行为)。若需感知构造期失败,使用 `await Source.create(...)` 或 `await source.ready`(失败时 reject)。 #### GeoJsonVT 瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/geojsonvt_tile_layer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/geojsonvt_tile_layer.md - Description: GeoJsonVT 瓦片 --- title: "GeoJsonVT 瓦片" description: "GeoJsonVT 瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/geojsonvt_tile_layer/" --- `L7` 矢量瓦片除了可以时候后端提供的瓦片服务之外,同时提供了 `geojson-vt` 瓦片切分方案,使得前端在没有后端支持的情况下也能使用矢量瓦片。 ### 矢量瓦片 - GeoJsonVT ```javascript import { PolygonLayer } from '@antv/l7'; fetch('https://gw.alipayobjects.com/os/bmw-prod/2b7aae6e-5f40-437f-8047-100e9a0d2808.json') .then((d) => d.json()) .then((data) => { const source = new Source(data, { parser: { type: 'geojsonvt', maxZoom: 9 }, }); const polygon = new PolygonLayer({ featureId: 'COLOR' }).source(source).color('red'); }); ``` ### sourceLayer 在使用前端瓦片切分的时候我们不再需要为瓦片图层指定数据源。 ### source(GeoJsonData: string, option: IOption) 在使用前端瓦片切分的矢量瓦片时,`source` 方法接收的不在时数据服务的地址,而是标准的 `GeoJSON` 数据。 #### option 在使用前端瓦片切分的时候我们需要将 `source parser` 的类型设置为 `geojsonvt`。 ```js const source = new Source(data, { parser: { type: 'geojsonvt', maxZoom: 9, geojsonvtOptions: {}, }, }); ``` `geojsonOptions` 支持如下参数: | 参数 | 类型 | 默认值 | 描述 | | | -------------- | ----------- | -------- | -------------------------------------------------------------- | ------------------------------------------------------- | | maxZoom | `number` | `14` | max zoom to preserve detail on | | indexMaxZoom | `number` | `5` | max zoom in the tile index | | indexMaxPoints | `number` | `100000` | max number of points per tile in the tile index | | tolerance | `number` | `3` | simplification tolerance (higher means simpler) | | extent | `number` | `4096` | tile extent | | buffer | `number` | `64` | tile buffer on each side | | lineMetrics | `boolean` | `false` | whether to calculate line metrics | | promoteId | `string` | `null` | `null` | name of a feature property to be promoted to feature.id | | generateId | `boolean` | `true` | whether to generate feature ids. Cannot be used with promoteId | | debug | `0, 1 or 2` | `0` | logging level (0, 1 or 2) | #### Raster 栅格瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/raster_tile_layer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/raster_tile_layer.md - Description: Raster 栅格瓦片 --- title: "Raster 栅格瓦片" description: "Raster 栅格瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/raster_tile_layer/" --- `L7` 的栅格图层支持加载 `TMS`、`WMS`、`WMTS` 等多种格式的图片瓦片,同时也支持 `Tiff`、`Lerc` 等多种格式的数据栅格瓦片。 | 分类 | Layer | parserType | dataType | 描述 | | -------- | ------------- | ------------ | ------------- | ---------------- | | 栅格瓦片 | `RasterLayer` | `rasterTile` | `image`、`/` | 图片栅格 | | 栅格瓦片 | `RasterLayer` | `rasterTile` | `arraybuffer` | 数据栅格 | | 栅格瓦片 | `RasterLayer` | `rasterTile` | `rgb` | 彩色遥感影像栅格 | 🌟 目前只支持 3857 坐标系 ### source(url: string, option: IOption) 矢量瓦片的数据源需要传入矢量数据的瓦片服务以及对应的配置参数。 #### url 数据服务的路径处理支持单服务和多服务的写法,还支持同时请求多文件。 - 单服务器 向一台服务器请求瓦片数据。 - 多服务器 向多台服务器请求同一份服务的瓦片数据。 - 使用大括号的写法请求设置多服务器,如 `{1-3}`、`{a-c}`。 - 请求多文件 同时请求多份瓦片服务的瓦片数据。 - 使用数组的方式设置多服务。 - 目前请求多文件的格式只有栅格瓦片支持。 ```js import { Source } from '@antv/l7' // 单服务器 const source = new Source('http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {...}) // 多服务器 const source = new Source('http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {...}) // 请求多文件 const urls = [ 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff', 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff', ] const urls = [ { url: 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff', bands: [0] }, { url: 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff' }, ... ] const tileSource = new Source(urls, {...}); ``` #### source option 通过配置 `parser` 中的参数,我们可以指定不同的瓦片类型以及瓦片服务的参数。 ```js const source = new Source(url, { parser: {...} }) ``` | 参数 | 类型 | 默认值 | 描述 | | -------------- | ---------------------------------- | ------------------------------------------ | -------------------- | | type | `string` | / | 描述不同类型的瓦片 | | tileSize | `number` | `256` | 请求的瓦片尺寸 | | minZoom | `number` | `0` | 请求瓦片的最小层级 | | maxZoom | `number` | `Infinity` | 请求瓦片的最大层级 | | zoomOffset | `number` | `0` | 请求瓦片层级的偏移量 | | extent | `[number, number, number, number]` | `[-Infinity,-Infinity,Infinity,Infinity,]` | 请求瓦片的边界 | | updateStrategy | `UpdateTileStrategy` | `replace` | 瓦片的替换策略 | ```js type UpdateTileStrategy = 'realtime' | 'overlap' | 'replace'; ``` 关于不同的栅格瓦片使用不同的 `parser` 参数。 | 瓦片类型 | type | dataType | 描述 | | ----------- | ------------ | ------------- | ---------------- | | TMS | `rasterTile` | `image` | 图片栅格 | | WMS | `rasterTile` | `image` | 图片栅格 | | WMTS | `rasterTile` | `image` | 图片栅格 | | arraybuffer | `rasterTile` | `arraybuffer` | 数据栅格,单通道 | | rgb | `rasterRgb` | `arraybuffer` | 数据栅格,多通道 | 🌟 `WMTS` 格式的瓦片有额外的参数。 | 参数 | 类型 | 值 | 描述 | | ------------- | -------------- | --- | ------------ | | `wmtsOptions` | `IWmtsOptions` | `/` | 设置请求参数 | `IWmtsOptions` 的参数用于拼接 `url`。 ```js interface IWmtsOptions { layer: string; version?: string; style?: string; format: string; service?: string; tileMatrixset: string; } ``` #### parser 参数 ##### type: string 用于指定瓦片服务的解析方式,值为 `rasterTile` 和 `mvt`。 `rasterTile` 用于栅格瓦片的解析,`mvt` 用于矢量瓦片的解析。 ##### dataType: string 使用 `dataType` 区分图片栅格和数据栅格,值为 `image` 和 `arraybuffer`,默认为 `image`。 ```javascript // 设置图片栅格 layer.source({ 'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', dataType: 'image', ... } } }) // 设置数据栅格 layer.source({ 'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', dataType: 'arraybuffer', ... } } }) ``` ##### minZoom/maxZoom: number 设置瓦片数据的请求层级。当地图的缩放层级 `zoom` 小于 `minZoom` 后,或 `zoom` 大于 `maxZoom` 后将不再请求新的瓦片。 `minZoom` 的默认值为 `-Infinity`。 `maxZoom` 的默认值为 `Infinity`。 ##### tileSize: number 设置的值是瓦片服务返回的瓦片大小。 `tileSize` 的默认值为 256。 ps: 该值在生产瓦片的时候确定,我们设置的 `tileSize` 需要和瓦片服务返回的保持一致。 ##### extent: [number, number, number, number] 设置请求瓦片数据的边界, 格式是 `[minLng, maxLat, maxLng, minLat]`,只会请求范围内的瓦片数据。 ##### zoomOffset: number 设置的值用于改变请求的瓦片数据的层级,通常在移动端可以请求更高一级的瓦片以获取更好的清晰度。 `zoomOffset` 的默认值为 0 ##### format: IRasterFormat _IFormat_ **必选** `format` 方法用于从传入的栅格文件二进制数据中提取波段数据。 - 第一个参数是栅格文件二进制数据。 - 第二个参数是第一个参数指定的栅格文件中应该提取的波段,方法参数是我们通过 `source` 参数传递的 `data` 数值。 - `format` 是一个 `async` 方法。 ```js interface IRasterData { rasterData: HTMLImageElement | Uint8Array | ImageBitmap | null | undefined; width: number; height: number; } type IRasterFormat = ( data: ArrayBuffer, bands: number[], ) => Promise; const source = new Source(data, { parser: { format: async (data, bands) => { ... return { rasterData: bandData, width: 256; height: 256; } } } }) ``` ## style - 单通道 绘制结果由是单一的数值控制,如灰度图,数值对应的颜色可以通过表示配置 `rampColors` 色带控制。 ```js layer.style({ opacity: 0.5, }); ``` ### options | style | 类型 | 描述 | 默认值 | | ----------- | ------------------ | ------------------------------------------- | ------------- | | opacity | `number` | 图形的透明度 | `1` | | clampLow | `boolean` | 设置为 `true`,低于 `domain` 的数据将不显示 | `false` | | clampHigh | `boolean` | 设置为 `true`,高于 `domain` 的数据将不显示 | `false` | | domain | `[number, number]` | 数据映射区间 | `[ 0, 8000 ]` | | noDataValue | `number` | 不会显示的值 | `-9999999` | | rampColors | `IRampColors` | 值域映射颜色的色带 | `/` | ### rampColors 颜色色带 - type 类型 支持 `linear','quantize','custom','cat' - colors 颜色数组 - positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值 ⚠️ 2.13 新增特性 #### cat 枚举类型色带 枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举 ```tsx { type:'cat', colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'], positions:[1,20,101,102,200], } ``` #### quantize 等间距分类色带 等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。 等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数 ```tsx rampColors: { type:'quantize', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'] } ``` #### linear 线性连续色带 linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1 ```tsx rampColors: { type:'linear', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions [0,200,1000,4000,8000] } ⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。 ``` #### custom 自定义分段色带 自定义分段色带区别等间距色带,用户自定义分段间隔。 自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions ```tsx rampColors: { type:'custom', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions: [0,200,1000,4000,8000,10000] } ``` #### Vector 矢量瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/vector_tile_layer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/vector_tile_layer.md - Description: Vector 矢量瓦片 --- title: "Vector 矢量瓦片" description: "Vector 矢量瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/vector_tile_layer/" --- ### 简介 `L7` 的矢量瓦片图层复用了普通图层的数据可视化能力,支持对图层的样式进行数据映射。目前矢量瓦片支持了点、线、面、掩模等图层 | 分类 | Layer | parserType | 描述 | | -------- | ---------------- | ----------------------------------- | ----------------------------------------- | | 矢量瓦片 | `PointLayer` | parser of PointLayer、`geojsonvt` | 矢量点图层 | | 矢量瓦片 | `LineLayer` | parser of LineLayer、`geojsonvt` | 矢量线图层 | | 矢量瓦片 | `PolygonLayer` | parser of PolygonLayer、`geojsonvt` | 矢量几何体图层 | | 矢量瓦片 | `MaskLayer` | parser of MaskLayer、`geojsonvt` | 矢量掩模图层 | | 矢量瓦片 | `TileDebugLayer` | `/` | `TileDebugLayer` 不需要执行 `source` 方法 | 瓦片图层其他配置项和基础图层 PointLayer、Linelayer、PolygonLayer 保持一致 ### options #### sourceLayer _string_ **required** 只有矢量图层生效,用于设置矢量图层的数据源。 🌟 一般矢量服务返回的数据中存在多个图层的数据,我们需要从中进行选取。 ```javascript const layer = new PointLayer({ sourceLayer: 'city', }); ``` #### featureId _string_ **optional** _default:_ 自动数字编号 只有矢量图层生效,用于指定矢量图层的编码 `id`。 🌟 编码 `id` 用于在图层高亮时使用。 ```javascript const layer = new PointLayer({ featureId: 'id', }); ``` ### source(url: string, option: IOption) 矢量瓦片的数据源需要传入矢量数据的瓦片服务以及对应的配置参数。 #### url 数据服务的路径支持单服务和多服务的写法。 - 单服务器 向一台服务器请求瓦片数据。 - 多服务器 向多台服务器请求同一份服务的瓦片数据。 - 使用大括号的写法请求设置多服务器,如 `{1-3}`、`{a-c}`。 ```js // 单服务器 const source = new Source('http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {...}) // 多服务器 const source = new Source('http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {...}) ``` #### source option 关于配置参数我们需要关系的是里面 `parser` 字段对应的参数。 ```js const source = new Source(url, { parser: {...} }) ``` | 参数 | 类型 | 默认值 | 描述 | | -------------- | ---------------------------------- | ------------------------------------------ | -------------------- | | type | `string` | / | 固定值为 `mvt` | | tileSize | `number` | `256` | 请求的瓦片尺寸 | | minZoom | `number` | `0` | 请求瓦片的最小层级 | | maxZoom | `number` | `Infinity` | 请求瓦片的最大层级 | | zoomOffset | `number` | `0` | 请求瓦片层级的偏移量 | | extent | `[number, number, number, number]` | `[-Infinity,-Infinity,Infinity,Infinity,]` | 请求瓦片的边界 | | updateStrategy | `UpdateTileStrategy` | `replace` | 瓦片的替换策略 | ```js type UpdateTileStrategy = 'realtime' | 'overlap' | 'replace'; ``` 🌟 矢量瓦片推荐复用 Source ```js const vectorSource = new Source( 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf', { parser: { type: 'mvt', maxZoom: 9, extent: [-180, -85.051129, 179, 85.051129], }, }, ); // 复用 layer1.source(vectorSource); layer2.source(vectorSource); ``` #### 图层基类 BaseLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/base_layer/base/ - Markdown source: https://l7.antv.antgroup.com/zh/api/base_layer/base.md - Description: 图层基类 BaseLayer --- title: "图层基类 BaseLayer" description: "图层基类 BaseLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/base_layer/base/" --- ## 简介 L7 Layer 接口设计遵循图形语法,所有图层都继承于基类(baseLayer)。 语法示例 ```javascript const layer = new BaseLayer(option) // option - 传入构造函数的参数对象,提供 layer 的初始状态 .source(...) // 传入图层需要的数据以及相关的解析器 .filter() // 数据过滤方法 .shape(...) // 为图层指定具体的形状,如:circle/triangle 等 .color(...) // 指定图层的颜色配置 .texture(...) // 指定图层引用的纹理 .size(...) // 设置图层元素的大小 .animate(...) // 设置图层元素的动画模式 .active(...) // 指定图层元素是否支持划过选中 .select(...) // 指定图层元素是否支持点击选中 .style(...); // 指定图层自定义样式的配置 scene.addLayer(layer); ``` ## options ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` ## 数据方法 ### source 数据 设置图层数据以及解析配置 `source(data, config)`。 - data { geojson | json | csv } - config 可选 数据源配置项 - parser 数据解析,默认是解析层 geojson - transforms [transform,transform ] 数据处理转换可设置多个 `parser` 和 `transforms` [见 source 文档](/zh/api/source/source)。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'map', callback: function (item) { const [x, y] = item.coordinates; item.lat = item.lat * 1; item.lng = item.lng * 1; item.v = item.v * 1; item.coordinates = [x * 1, y * 1]; return item; }, }, { type: 'hexagon', size: 6000, field: 'v', method: 'sum', }, ], }); ``` ### cluster 我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 #### getClusters(zoom: number): IFeatureCollection 获取指定缩放等级的聚合数据 - `zoom` 缩放等级 #### getClustersLeaves(id: string): IFeatureCollection 根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - `id` 聚合节点的 `id` ```ts const source = layer.getSource(); source.getClustersLeaves(id); layer.on('click', (e) => { console.log(source.getClustersLeaves(e.feature.cluster_id)); }); ``` ## scale 数据度量 Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ### scale [Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) 参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleOptions` 列定义配置,对象类型 - type scale 类型 - unknown 未匹配颜色 可选 默认透明 - domain 值域 可选 ```javascript interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` #### 类型 Range 和 domain 是 Scale 中非常重要的两个参数 domain: 地图数据值的定义区间 range:视觉值的区间 不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 数据值和映射值相同 比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s ``` // 设置为 identify layer.scale('value', { type: 'identify' }); // 或者 layer.scale('value'); // L7 能够自动推断为 identify ``` #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 ### getScale(scaleName:string) 根据视觉通道名称获取 scale 实例,调用之前确保 layer 已经初始化完成 ```ts const scale = layer.getScale('color'); const color = scale(1); // 将数值转换成颜色 ``` 更多是方法 scale 示例使用 ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 ### filter 数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 ```ts pointLayer.filter('type', (type) => { // 回调函数 if (type === 'a') { return false; } return true; }); ``` ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 ```javascript pointLayer.size(10); // 常量 pointLayer.size('type'); // 使用字段映射到大小 pointLayer.size('type', [0, 10]); // 使用字段映射到大小,并指定最大值和最小值 pointLayer.size('type', (type) => { // 回调函数 if (type === 'a') { return 10; } return 5; }); ``` #### size(value) 传入数字常量,如 `pointLayer.size(20)` #### size(field) 根据 field 字段的值映射大小,使用默认的`最大值 max:10` 和`最小值 min: 1`。 #### size(field, callback) 使用回调函数控制图形大小。 - `callback`: function 回调函数。 ```javascript pointLayer.size('age', (value) => { if (value === 1) { return 5; } return 10; }); ``` ### color 将数据值映射到图形的颜色上的方法。 ```javascript layer.color('red'); // 常量颜色 layer.color('type'); // 对 type 字段进行映射,使用内置的颜色 layer.color('type', ['red', 'blue']); // 指定颜色 layer.color('type', (type) => { // 通过回调函数 if (type === 'a') { return 'red'; } return 'blue'; }); layer.color('type*value', (type, value) => { //多个参数,通过回调函数 if (type === 'a' && value > 100) { return 'red'; } return 'blue'; }); ``` #### color(value) 参数:`value` :string 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 示例 ```javascript layer.color('name'); // 映射数据字段 layer.color('white'); // 指定颜色 ``` #### color(field, colors) 参数: - `field`: stringfield 为映射至颜色属性的数据源字段名,也支持指定多个参数。 - `colors`: string | array | function colors 的参数有以下情况: 如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript layer.scale('name',{ type:'quantile' unknown:'#ccc' // 设置无效颜色 }) layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` - colors 如果是回调函数,则该回调函数的参数为对应字段的数值,具体使用如下,当 color 映射为多个字段时,参数按照字段声明的顺序传入: ```javascript layer.color('gender', (value) => { if (value === 1) { return 'red'; } return 'blue'; }); layer.color('gender*age', (gender, age) => { if (age === 20 && gender == ' 男') { return 'red'; } return 'blue'; }); ``` ### shape 通常一种图层可以有多种表现形式,shape 方法用于指定图层具体的表现形式,以 PointLayer 的 shape 为例: ```javascript shape('circle'); // 圆形 shape('triangle'); // 三角形 shape('cylinder'); // 圆柱 ``` **shape(shape)** 参数 `shape` string - 只支持接收一个参数,指定几何图像对象绘制的形状。下表列出了不同的 图层 几何图形对象支持的 shape 形状 | layer 类型 | shape 类型 | 备注 | | ---------- | -------------------------------------------------------------------------------------- | ---- | | point | 2d:point,circle, square, triangle,hexagon,image,text 3d:circle,triangle,hexagon,square | | | line | line,arc, arc3d, greatcircle | | | polygon | fill,line, extrude | | **shape(field, shapes)** - shape 根据字段指定行形状,比如根据字段指定 PointLayer/imageLayer 的 icon 类型 ```javascript 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); ``` [在线案例](/zh/examples/point/image/image/) **shape(field, callback)** - shape 也支持回调函数的写法 ```javascript .shape('key', value => { if(value > 10) { return 'circle'; } else { return 'triangle'; } } ``` ### rotate 将数据值映射到图形的旋转角度上的方法,用于控制点图层图标/图形的旋转。 ```javascript layer.rotate(45); // 常量,所有元素旋转 45 度 layer.rotate('angle'); // 字段映射 layer.rotate('angle', [0, 360]); // 字段映射到角度范围 layer.rotate('angle', (angle) => { return angle * (Math.PI / 180); // 回调函数 }); ``` ### label 为图层设置标注(文字标签),将数据字段映射为标注内容显示在图层元素旁边。主要在特定图层类型(如 PointLayer 的文字标注)中生效。 ```javascript layer.label('name'); // 以 name 字段的值作为标注文本 layer.label('name', (name) => `${name}市`); // 回调函数处理标注文本 ``` ### style style 方法通常用于描述图层具体的样式,大多数图层会支持一些比较通用的属性, 如 opacity 属性,同时每个图层也会有仅限本图层支持的属性,如只有 CityBuildingLayer 支持的 windowColor 属性,每个图层具体要如何配置属性请查看每个图层的详细文档。 - opacity 设置透明度 大部分图层都支持 - stroke 线填充颜色 仅点图层支持 - strokeWidth 线的宽度 仅点图层支持 ```javascript layer.style({ opacity: 0.8, stroke: 'white', }); ``` - 样式数据映射🌟 在正常情况下,style 的参数会作用到一个图层上的所有图形,如一个 PointLayer 中有十个点,我们设置 opacity = 0.5, 这样十个点的透明度都是 0.5。 而在特殊情况下,我们可能需要为每个点分别设置一个透明度,这时候按照原来的方式直接设置 style 方法的 opacity 的值就无法满足需求了,为此我们需要提供特殊的赋值方式。 通常我们会根据传入图层的数据为图层的每个图形设置单独的值,因此我们称之为“样式数据映射”。 我们支持几种设置 style 中的参数从 source 数据中动态取值的写法。 ```javascript // 根据数据中的 v 字段的值设置点图层各个点的透明度 const data = [ { lng: 120, lat: 30, v: 0.5 }, ... ] const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat' } }) .shape('circle') .color('#f00') .size({ // 第一种写法 根据字段从 data 中直接取值 opacity: 'v'// opacity = 0.5 }); scene.addLayer(layer); ``` [在线案例](/zh/examples/point/text/style-map/) 从 `L7 2.5` 开始,各图层样式将逐步支持样式数据映射,目前支持样式数据映射的 `style` 参数如下: | layer 类型/shape | 支持的样式字段 | 备注 | | ---------------------- | ---------------------------------------------------- | --------------------------------- | | pointLayer/fill | opacity、strokeOpacity、strokeWidth、stroke、offsets | shape circle、triangle... | | pointLayer/image | opacity、offsets | offsets 经纬度偏移 | | pointLayer/normal | opacity、offsets | | | pointLayer/text | opacity、strokeWidth、stroke、textOffset | textOffset 相对文字画布位置的偏移 | | pointLayer/extrude | opacity | | | polygonLayer/fill | opacity | | | polygonLayer/extrude | opacity | | | lineLayer/line | opacity | | | lineLayer/arc | opacity、thetaOffset | thetaOffset 弧线的弯曲弧度 | | lineLayer/arc3d | opacity | | | lineLayer/great_circle | opacity | | [在线案例](/zh/examples/point/scatter/scatter-style-map/) ### texture 目前只在线图层上支持了纹理方法 - texture 方法支持传入由 scene.addImage 方法添加的全局 icon 贴图资源 ```javascript // 首先在全局加载图片资源 scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/0ca1668e-38c2-4010-8568-b57cb33839b9.svg', ); const layer = new LineLayer({ blend: 'normal', }) .source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(25) .shape('arc') .texture('plane') // 为图层绑定纹理 .color('#8C1EB2') .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](/zh/examples/line/animate/plane-animate2/) ## 图层更新方法 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 ### scale 更新 重新调用scale 方法 ```tsx layer.scale('value', { type: 'quantile', }); scene.render(); ``` ### 数据映射 重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); scene.render(); ``` ### layer.style ```javascript layer.style({ opacity: 1, }); scene.render(); ``` ### setData(data, option?: {}) 更新 Source 数据 参数: - data 数据 - option 默认和初始配置项一致,如果数据格式相同可不设置 调用 setData 方法会自动更新图层渲染 ```javascript layer.setData(data); ``` ### setBlend(type: string) 设置图层叠加方法 参数: - type blend 类型 normal | additive | subtractive | max ## 图层控制方法 ### show() 图层显示 ```javascript layer.show(); ``` ### hide() 图层隐藏 ```javascript layer.hide(); ``` ### isVisible(): boolean 图层是否可见 ```javascript layer.isVisible(); ``` ### setIndex(zIndex: int) 设置图层绘制顺序 ```javascript layer.setIndex(1); ``` ### fitBounds() 缩放到图层范围 ```javascript layer.fitBounds(); ``` ### setMinZoom(zoom: number) 设置图层最小缩放等级 ```javascript layer.setMinZoom(zoom); ``` ### setMaxZoom(zoom: number) 设置图层最大缩放等级 参数 - zoom {number} ```javascript layer.setMaxZoom(zoom); ``` ### getMinZoom(): number 获取图层最小缩放等级 ```javascript const minZoom = layer.getMinZoom(); ``` ### getMaxZoom(): number 获取图层最大缩放等级 ```javascript const maxZoom = layer.getMaxZoom(); ``` ### destroy() 销毁图层,释放相关资源。场景调用 `removeLayer` 时会自动销毁图层,一般不需要手动调用。 ```javascript layer.destroy(); ``` ## 图层交互方法 ### active(activeOption | boolean) - 开启或者关闭 mousehover 元素高亮效果 - `activeOption` - `color`: 高亮颜色 - `mix`: 可选参数,默认为 0,表示高亮颜色是指定纯色,最大有效值是1,表示高亮色全部是底色 ```javascript activeOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.active(true); // 开启 Active 自定义高亮颜色 layer.active({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.active(false); ``` ### setActive(featureId: int) 根据元素 ID 设置指定元素 hover 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setActive(featureId); ``` ### select(selectOption | boolean) - 开启或者关闭 mouseclick 元素选中高亮效果 - selectOption - `color`: 选中高亮颜色 - `mix`: 可选参数,默认为 0,表示选中高亮颜色是指定纯色,最大有效值是1,表示选中高亮色全部是底色 ```javascript selectOption: { color: '#f00'; mix: 0.6; } ``` ```javascript // 开启 Active 使用默认高亮颜色 layer.select(true); // 开启 Active 自定义高亮颜色 layer.select({ color: 'red', mix: 0.6, }); // 关闭高亮效果 layer.select(false); ``` ### setSelect(featureId: int) 根据元素 ID 设置指定元素 click 选中 高亮 🌟 指定元素高亮不等于图层高亮,一个图层包含多个元素,一般传入 source 的数据数组中有多少单条数据,一个图层就有多少元素 ```javascript layer.setSelect(featureId); ``` ### setAutoFit(autoFit: boolean) 让用户可以主动设置图层的 autoFit 参数 🌟 设置完该方法后会在图层发生更新的时候生效,如在 setData 之后触发 ```javascript // 使用方法 layer.setAutoFit(true); // 内部实现 public setAutoFit(autoFit: boolean): ILayer { this.updateLayerConfig({ autoFit, }); return this; } ``` ### getScale(attr: string) 支持单独获取某个图形经过 scale 计算后的值, 满足用户获取图层某些 feature 值的需求。 - attr scale 的属性值 ```javascript const data = [ { lng: 120, lat: 30, name: 'n1' }, { lng: 120, lat: 30, name: 'n2' }, ]; const layer = new PointLayer() .source(data, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('circle') .color('name', ['#f00', '#ff0']) .size('name', [20, 40]); scene.addLayer(layer); // 此时在 scene 上绘制两个点 // 一个颜色为黄色,大小为 40 的点,对应 name 为 n1 // 一个颜色为红色,大小为 20 的点,对应 name 为 n2 const colorScale = layer.getScale('color'); // 获取 color 方法产生的 scale const color1 = colorScale('n1'); // '#ff0' const color1 = colorScale('n2'); // '#f00' const sizeScale = layer.getScale('size'); // 获取 size 方法产生的 scale const size1 = sizeScale('n1'); // 40 const size2 = sizeScale('n2'); // 20 ``` ### getLegendItems(type: string) 不推荐使用,将废弃, 获取图例配置 - type 图例类型 - index 可选 默认 ```javascript layer.getLegendItems('color'); layer.getLegendItems('size'); ``` ### getLegend(type: string) getLegendItems方法的替代方法 该方法需要 返回值 - type 图例类型 - field 映射字段 - items 图例项 ```javascript layer.getLegend('color'); layer.getLegend('size'); ``` 注:rasterayer 只支持 color 类型 ## 图层掩模方法 ### addMask 添加 Mask 图层 ```ts const polygonLayer = new Polygon(); layer.addMask(polygonLayer); scene.render(); ``` ### removeMask ```ts const polygonLayer = new Polygon(); layer.removeMask(polygonLayer); scene.render(); ``` ### disableMask ```ts layer.disableMask(); scene.render(); ``` ### enableMask ```ts layer.enableMask(); scene.render(); ``` ## 鼠标事件 鼠标事件回调参数 target ```javascript layer.on(eventName, (target) => console.log(target)); ``` - x: number 鼠标 在地图位置 x 坐标 - y: number 鼠标 在地图位置 y 坐标 - type: string 鼠标事件类型 - lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度 - feature: any; 数据选中的地理要素信息 - featureId: number | null; 数据选中的地理要素的 ID ### click 点击事件 ```javascript layer.on('click', (e) => console.log(e)); ``` ### dblclick 双击 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mousemove 鼠标移动事件 ```javascript layer.on('mousemove', (e) => console.log(e)); ``` ### mouseout 鼠标移除 ```javascript layer.on('mouseout', (e) => console.log(e)); ``` ### mouseup 鼠标抬起 ```javascript layer.on('mouseup', (e) => console.log(e)); ``` ### mousedown 鼠标按下 ```javascript layer.on('mousedown', (e) => console.log(e)); ``` ### contextmenu 鼠标右键 ```javascript layer.on('contextmenu', (e) => console.log(e)); ``` ### dblclick 双击拾取元素 ```javascript layer.on('dblclick', (e) => console.log(e)); ``` ### mouseenter 鼠标进入图层要素时触发 ```javascript layer.on('mouseenter', (e) => console.log(e)); ``` ### unclick 点击未拾取到元素 ```javascript layer.on('unclick', (e) => console.log(e)); ``` ### unmousemove 鼠标移动未拾取到元素 ```javascript layer.on('unmousemove', (e) => console.log(e)); ``` ### unmouseup 鼠标抬起未拾取到元素 ```javascript layer.on('unmouseup', (e) => console.log(e)); ``` ### unmousedown 鼠标按下未拾取到元素 ```javascript layer.on('unmousedown', (e) => console.log(e)); ``` ### uncontextmenu 鼠标右键位拾取到元素 ```javascript layer.on('uncontextmenu', (e) => console.log(e)); ``` ### unpick 所有鼠标事件未拾取到 ```javascript layer.on('unpick', (e) => console.log(e)); ``` ### touchstart 移动端事件 touchstart ```javascript layer.on('touchstart', (e) => console.log(e)); ``` ### touchend 移动端事件 touchend ```javascript layer.on('touchend', (e) => console.log(e)); ``` 使用示例 ```javascript layer.on('click', (ev) => {}); // 鼠标左键点击图层事件 layer.on('mouseenter', (ev) => {}); // 鼠标进入图层要素 layer.on('mousemove', (ev) => {}); // 鼠标在图层上移动时触发 layer.on('mouseout', (ev) => {}); // 鼠标移出图层要素时触发 layer.on('mouseup', (ev) => {}); // 鼠标在图层上单击抬起时触发 layer.on('mousedown', (ev) => {}); // 鼠标在图层上单击按下时触发 layer.on('contextmenu', (ev) => {}); // 图层要素点击右键菜单 // 鼠标在图层外的事件 layer.on('unclick', (ev) => {}); // 图层外点击 layer.on('unmousemove', (ev) => {}); // 图层外移动 layer.on('unmouseup', (ev) => {}); // 图层外鼠标抬起 layer.on('unmousedown', (ev) => {}); // 图层外单击按下时触发 layer.on('uncontextmenu', (ev) => {}); // 图层外点击右键 layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件 ``` ## 图层事件 ### inited 参数 option - target 当前 layer - type 事件类型 图层初始化完成后触发 ```javascript layer.on('inited', (option) => {}); ``` ### add 图层添加到 scene 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('add', (type) => console.log(type)); ``` ### remove 图层移除时触发 参数 option - target 当前 layer - type 事件类型 ```javascript layer.on('remove', (type) => console.log(type)); ``` ### legend 数据映射更新,图例发生变化,主要 color、size ### `legend:color` 数据映射更新,图例 color 颜色改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:color', (ev) => console.log(ev)); ``` ### `legend:size` 数据映射更新,图例 size 大小改变 参数 option: - type 图例类型 - field 映射字段 - items 图例项 ```js layer.on('legend:size', (ev) => console.log(ev)); ``` ## 图层框选 ### boxSelect 参数 option - box [x1: number, y1: number, x2: number, y2: number] 相较于 - cb (...args: any[]) => void 传入的回调方法,返回框选内部的 feature ```javascript layer.boxSelect(box, cb); // (x1, y1), (x2, y2) 框选的方框左上角和右下角相对于地图左上角的像素坐标 // cb 是传入的回调函数,回调函数返回的参数是选中的 feature 对象数组,对象的字段和用户传入的数据相关 ``` #### 控件 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/control/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/control.md - Description: 控件 --- title: "控件" description: "控件" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/control/" --- 地图控件指的是悬停在地图四周,可以对地图以及图层等元素进行**信息呈现**或**交互**的组件。  ## 使用 ```ts import { Scene, Zoom } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { // 实例化 Zoom 控件,可以在构造器中传入控件的配置 const zoom = new Zoom({ position: 'leftbottom', className: 'my-test-class', }); // 将实例化的控件添加至 L7 中 scene.addControl(zoom); }); ``` ## 更新配置 在控件实例化之后,如果需要更新配置,可以调用控件实例的 `setOptions` 方法,同时传入需要更新的配置对象即可。 ```ts const zoom = new Zoom({ position: 'leftbottom', }); const onPositionChange = () => { // 通过 setOptions 传入需要更新的配置对象 zoom.setOptions({ position: 'topright', }); }; ``` ## 插槽 当前 L7 中的控件支持插入到地图的**左上、左下、右上、右下、上、左、下、右**八个位置插槽或者用户自定义的 `DOM` 中,并且在同一地图插槽中,多个控件之间支持**横向**和**纵向**排列。 在初始化所有的控件类时,可以传入 `position` 参数来设置控件对应的插槽以及排列方式。  ## 配置 | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### LayerPopup 图层信息框 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/layer_popup/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/layer_popup.md - Description: LayerPopup 图层信息框 --- title: "LayerPopup 图层信息框" description: "LayerPopup 图层信息框" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/layer_popup/" --- LayerPopup 基于 Popup 封装的,专门用于展示图层元素信息的气泡。 ## 说明 LayerPopup 是为了让开发者通过配置快速生成用于展示图层信息的气泡,开发者可以传入需要展示信息气泡的图层,以及需要展示的字段。 LayerPopup 会自行对目标图层的鼠标事件进行监听,当用户点击/悬停在目标图层的某一元素上时,会自动打开 Popup 并展示该元素的字段值。 ## 使用 [示例](/zh/examples/component/popup/layerpopup/) [自定义内容示例](/zh/examples/component/popup/customcontent/) ```ts import { Scene, LayerPopup, PointLayer } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMapV2({ // ... }), }); scene.on('loaded', () => { const pointLayer = new PointLayer(); pointLayer.source( [ { lng: 120, lat: 30, name: 'Test 1', }, ], { parser: { type: 'json', x: 'lng', y: 'lat', }, }, ); scene.addLayer(pointLayer); const layerPopup = new LayerPopup({ items: [ { layer: pointLayer, fields: [ { field: 'name', formatValue: (name?: string) => name.trim() ?? '-', }, ], }, ], trigger: 'hover', }); scene.addPopup(popup); }); ``` ## 配置 | 名称 | 说明 | 类型 | 默认值 | | ------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------- | | items | 需要展示 Popup 的图层配置数组,每个选项类型可见 [LayerPopupConfigItem](#layerpopupconfigitem) | `Array` | `[]` | | trigger | 鼠标触发 Popup 展示的方式,`'click'` 在移动端会自动转换为 `'touchend'` | `'hover' \| 'click' \| 'touchend' \| 'touchstart'` | `'hover'` | ### LayerPopupConfigItem | 名称 | 说明 | 类型 | | ------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | | layer | 需要展示 Popup 的目标图层实例,或其的 `id` 或 `name` | `BaseLayer` \| `string` | | fields | 需要展示的字段数组,支持传入字段 key 值字符串,或者针对该字段的详细配置 [LayerField](#layerfield) | `string` \| `LayerField` | | customContent | 自定义气泡内容,支持直接传入自定义内容或者通过回调函数返回自定义内容两种方式,与 `fields` 共存下优先读取该配置并渲染 | `ElementType \| ((feature: any) => ElementType)` | | title | 自定义气泡标题,支持直接传入自定义内容或者通过回调函数返回自定义内容两种方式 | `ElementType \| ((feature: any) => ElementType)` | ### LayerField | 名称 | 说明 | 类型 | | ----------- | --------------------------- | --------------------------------------------------------------- | | field | 字段的 key 值字符串 | `string` | | formatField | 对展示的 key 字段进行格式化 | `ElementType \| ((field: string, feature: any) => ElementType)` | | formatValue | 对展示的 value 值进行格式化 | `ElementType \| ((value: any, feature: any) => ElementType)` | | getValue | 自定义获取值的方式 | `(feature: any) => any` | ### ElementType ```ts type ElementType = HTMLElement | HTMLElement[] | DocumentFragment | Text | string; ``` ## 方法 | 名称 | 说明 | 类型 | | ---------- | --------------------------- | -------------------------------------------------------------------- | | getOptions | 获取当前 Popup 配置 | `() => IPopupOption` | | setOptions | 更新当前 Popup 配置 | `(newOption: Partial) => this` | | show | 显示 Popup | `() => this` | | hide | 隐藏 Popup | `() => this` | | setLngLat | 设置 Popup 锚点所在经纬度 | `(lngLat: { lng: number; lat: number } \| [number, number]) => this` | | panToPopup | 将地图平移至当前 Popup 位置 | `() => this` | ## 事件 | 名称 | 说明 | 类型 | | ----- | ------------------ | ------------ | | open | Popup 被添加时触发 | `() => void` | | close | Popup 被移除时触发 | `() => void` | | show | Popup 显示时触发 | `() => void` | | hide | Popup 隐藏时触发 | `() => void` | #### Earth Mode - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/earth/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/earth.md - Description: Earth Mode --- title: "Earth Mode" description: "Earth Mode" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/earth/" --- ## 简介 l7-maps 提供 `Earth` 地图,相较于高德地图、mapbox 地图,是完全不同的一种表现形式,提供了全球视角下的可视化展示能力,为用户提供了更多的地理信息可视化表现形式。 ✨ 为了区别普通的地图,l7-maps 提供了全新的 `Earth` 地图类型, L7 提供对应的 `EarthLayer` 图层 ```js import { EarthLayer } from '@antv/l7'; import { Earth } from '@antv/l7-maps'; ``` ## 目前在地球模式下支持的图层类型 ### 点图层 **平面点: circle** **圆柱点: cylinder** ### 线图层 **3D 弧线: arc3d** ## 使用 ```javascript // 1、引入对应模块 import { Scene, Earth } from '@antv/l7-maps'; import { EarthLayer } from '@antv/l7-layers'; // 2、构建 Earth Map const scene = new Scene({ id: 'map', map: new Earth({}), }); // 3、构建地球图层,当前的 shape 为 base,表示基础球体 const earthlayer = new EarthLayer() .source( // 地球表面的纹理 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', { parser: { type: 'image', extent: [121.168, 30.2828, 121.384, 30.421], }, }, ) .color('#f00') .shape('base') .style({ opacity: 1.0, radius: 40, globalOptions: { ambientRatio: 0.6, // 环境光 diffuseRatio: 0.4, // 漫反射 specularRatio: 0.1, // 高光反射 earthTime: 0.1, }, }) .animate(true); scene.on('loaded', () => { // 4、添加基础地球球体 scene.addLayer(earthlayer); }); // 经过上述的步骤,我们就可以在场景中添加一个基础的地球了 ``` ## 独立的地图类型 Earth ### 构造函数 Earth 作为 l7-maps 的基础地图类型,`Earth` 提供了地球系统的相机系统,目前只需要传入一个空对象。 - args: **{}** ```js import { Scene, Earth } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Earth({}), }); ``` ### rotateY 提供了简单的方法控制地球系统的旋转(实际上控制的是相机的旋转,需要传入一个对象 - force: `false` 判断是否强制生效,默认该方法的优先级比用户鼠标操作要低,当用户操作相机的时候,该方法会失效 - reg: `0.01` 旋转的角度(视觉上地球的旋转角度), `reg` 表示的并不是实际的旋转角度,而是单位旋转角度的比例 🌟 单位旋转角度 = Math.min(this.earthCameraZoom \* this.earthCameraZoom, 1) ```js import { Scene, Earth } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Earth({}), }); function step() { scene.map.rotateY({ option: { force: true, reg: 0.1, }, }); requestAnimationFrame(step); } scene.on('loaded', () => { scene.addLayer(earthlayer); step(); }); ``` ## 地图图层 EarthLayer 地球图层区别于普通高德地图和 Mapbox 地图的图层,只在地球模式下可以被使用,用于表示地球的球体、大气层、辉光等效果。 🌟 使用不同的 `shape` 参数表示区别不同的地球图层。 ### 地球球体图层 baseLayer - source: 数据 - map: 地球表面纹理贴图的地址 - parser: 解析器,目前只需要写固定的对象值即可: `{ parser: { type: "image" } }` - shape: 图层类型 默认值是 `base`, 目前支持的 `shape` 类型有: - base: 球体 - atomSphere: 大气层 - bloomSphere: 辉光 当用户的 `shape` 参数不被识别时,自动降级为 `base` 类型 - globalOptions: 图层样式 - ambientRatio: 环境光 - diffuseRatio: 漫反射 - specularRatio: 高光反射 ```javascript const earthlayer = new EarthLayer() .source('https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', { parser: { type: 'image', }, }) .shape('base') .style({ globalOptions: { ambientRatio: 0.6, // 环境光 diffuseRatio: 0.4, // 漫反射 specularRatio: 0.1, // 高光反射 }, }); ``` ### 地球内发光/大气图层 atomLayer `atomLayer` 作为地球的效果图层,不需要传入数据,所以可以不调用 `source` 方法 ```javascript const atomLayer = new EarthLayer().color('#2E8AE6').shape('atomSphere').style({ // 可以控制发光程度 opacity: 1, }); ``` ### 地球内外发光/辉光图层 bloomLayer `bloomLayer` 作为地球的效果图层,不需要传入数据,所以可以不调用 `source` 方法 ```javascript const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere').style({ opacity: 0.5, }); ``` #### 简单坐标系(非地理坐标系) - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/simple_coordinates/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/simple_coordinates.md - Description: 简单坐标系(非地理坐标系) --- title: "简单坐标系(非地理坐标系)" description: "简单坐标系(非地理坐标系)" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/simple_coordinates/" --- 我们通常使用经纬度来描述地理位置,但是在某些特殊的场景,我们往往倾向于使用更加简单的平面坐标系(xyz)来描述位置的相对坐标,为此 L7 提供了简单坐标系的模式。 [在线案例](/zh/examples/point/text/simplecoordinate/) ### Map 为了使用简单坐标系,我们需要是使用 L7 自定义的 Map 地图类型,同时指定 map 的 version 属性 ```javascript import { Scene, ImageLayer, PointLayer } from '@antv/l7'; import { Map } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Map({ center: [500, 500], pitch: 0, zoom: 3, version: 'SIMPLE', mapSize: 1000, maxZoom: 5, minZoom: 2, pitchEnabled: false, rotateEnabled: false, }), }); ``` #### version 用户在使用自定义坐标系的时候,需要将地图的类型设置成 'SIMPLE' #### mapSize: number 用户在使用自定义坐标系的时候,可以设置绘图区域的大小。绘图区域默认是 10000 X 10000 的矩形区域,坐标起点是左下角,水平向右为 X 正方向,垂直向上是 Y 正方向。 #### pitchEnabled/rotateEnabled 用户在使用自定义坐标系的时候,推荐将 pitchEnabled/rotateEnabled 设置为 false #### layer 用户在使用自定义坐标系的时候,可以正常使用普通的图层,唯一的区别就是需要将原本的经纬度坐标转化为平面坐标 ```javascript const imagelayer = new ImageLayer({}).source( 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*I0X5R4jAUQ4AAAAAAAAAAAAAARQnAQ', { parser: { type: 'image', extent: [360, 400, 640, 600], }, }, ); const textlayer = new PointLayer({ zIndex: 2 }) .source( [ { x: 515, y: 575, t: '小屋', }, ... ], { parser: { type: 'json', x: 'x', y: 'y', }, }, ) .shape('t', 'text') .size(12) .active({ color: '#00f', mix: 0.9 }) .color('rgb(86, 156, 214)') .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left spacing: 2, // 字符间距 fontWeight: '800', padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#ffffff', // 描边颜色 strokeWidth: 2, // 描边宽度 textAllowOverlap: true, }); const lineData = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: { testOpacity: 0.8, }, geometry: { type: 'Polygon', coordinates: [ [ [6000, 6000], [6000, 7000], [7000, 7000], [7000, 6000], ], ], }, }, ], }; const linelayer = new LineLayer() .source(lineData) .shape('line') .size(10) .color('#0f0') .active(true); const polygonData = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: { testOpacity: 0.4, }, geometry: { type: 'MultiPolygon', coordinates: [ [ [ [6000, 6000], [6000, 7000], [7000, 7000], [7000, 6000], [6000, 6000], ], [ [6300, 6300], [6300, 6700], [6700, 6700], [6700, 6300], [6300, 6300], ], ], [ [ [5000, 5000], [5000, 6000], [6000, 6000], [6000, 5000], [5000, 5000], ], ], ], }, }, ], }; const polygonLayer = new PolygonLayer() .source(polygonData) .shape('fill') .color('#f00') .style({ opacity: 0.6, }) .active(true); ``` #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/image_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/image_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/image_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### 高德地图 - Canonical page: https://l7.antv.antgroup.com/zh/api/map/gaode/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/gaode.md - Description: 高德地图 --- title: "高德地图" description: "高德地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/gaode/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - [高德地图 官网](https://lbs.amap.com/api/javascript-api-v2/update) ## 申请token 高德地图 API 配置参数 - token 注册高德 [API token](https://lbs.amap.com/api/javascript-api/guide/abc/prepare) ## 地图初始化化 ```javascript const L7AMap = new GaodeMap({ pitch: 35.210526315789465, style: 'dark', center: [104.288144, 31.239692], zoom: 4.4, token: 'xxxx - token', plugin: [], // 可以不设置 }); ``` ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 ## 传入外部实例 为了支持已有地图项目快速接入 L7 的能力,L7 提供传入地图实例的方法。如果你是新项目推荐使用 Scene 初始化地图 ⚠️ scene id 参数需要地图的 Map 实例是同个容器。 ⚠️ 传入地图实例需要自行引入相关地图的 API ⚠️ viewMode 设置为 3D 模式(GaodeMap2.0 支持 2D 模式,可以不设置) #### 传入高德地图实例 ```javascript const map = new AMap.Map('map', { viewMode: '3D', resizeEnable: true, // 是否监控地图容器尺寸变化 zoom: 11, // 初始化地图层级 center: [116.397428, 39.90923], // 初始化地图中心点 }); const scene = new Scene({ id: 'map', map: new GaodeMap({ mapInstance: map, }), }); ``` [示例地址](/zh/examples/map/map/amapinstance/) [代码地址](https://github.com/antvis/L7/blob/master/examples/tutorial/map/demo/amapInstance.js) [示例地址( 2D )](/zh/examples/map/map/gaodemap/) [代码地址](https://github.com/antvis/L7/blob/master/examples/tutorial/map/demo/amapInstance.js) ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 ## 注册使用高德插件 ```javascript const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [116.475, 39.99], pitch: 0, zoom: 13, plugin: ['AMap.ToolBar', 'AMap.LineSearch'], }), }); // plugin: ['AMap.ToolBar', 'AMap.LineSearch'], // 为了使用对应插件的能力,应该首先在 plugin 中注册对应的插件 // 加载的 AMap 会挂载在全局的 window 对象上 scene.on('loaded', () => { window.AMap.plugin(['AMap.ToolBar', 'AMap.LineSearch'], () => { // add control scene.map.addControl(new AMap.ToolBar()); var linesearch = new AMap.LineSearch({ pageIndex: 1, //页码,默认值为1 pageSize: 1, //单页显示结果条数,默认值为20,最大值为50 city: '北京', //限定查询城市,可以是城市名(中文/中文全拼)、城市编码,默认值为『全国』 extensions: 'all', //是否返回公交线路详细信息,默认值为『base』 }); //执行公交路线关键字查询 linesearch.search('536', function (status, result) { //打印状态信息status和结果信息result // ... do something }); }); }); ``` [在线案例](/zh/examples/amap-plugin/bus/busstop/) #### SpriteGeometry - Canonical page: https://l7.antv.antgroup.com/zh/api/other/sprite/ - Markdown source: https://l7.antv.antgroup.com/zh/api/other/sprite.md - Description: SpriteGeometry --- title: "SpriteGeometry" description: "SpriteGeometry" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/other/sprite/" --- ## 简介 SpriteGeometry 是 L7 提供的通用的粒子图层,可以用来绘制各种粒子效果。 ### demo 设置普通的粒子图层。 ```javascript import { Scene, GeometryLayer } from '@antv/l7'; let layer = new GeometryLayer() .shape('sprite') .size(10) .style({ opacity: 0.3, center: [120, 30], spriteCount: 120, spriteRadius: 10, spriteTop: 300, spriteUpdate: 10, spriteScale: 0.6, }); ``` [在线案例](/zh/examples/geometry/geometry/snow/) ### source 🌟 SpriteGeometry 不需要设置 source,我们在 style 中通过 center 赋予其位置信息。 ### style SpriteGeometry 主要通过 style 方法设置位置、大小以及其他属性。 #### center: [lng: number, lat: number] 设置 SpriteGeometry 的位置,定位是 SpriteGeometry 的中心。 #### mapTexture: string 设置精灵的纹理贴图。 #### spriteRadius: number 粒子的作用半径,默认为 10。 🌟 单个粒子会在图层位置半径范围内随机分布。 #### spriteAnimate: string 粒子的运动、默认为 'down',表示向下运动。可选值有 'down'/'up'。 #### spriteCount: number 图层生成的粒子数量,默认为 100。 #### spriteTop: number 粒子运动的高度范围,默认为 300. #### spriteUpdate: number 粒子运动刷新的步长,表现为运动速度、默认为 10。 #### spriteScale: number 粒子大小缩放、默认为 1。 #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/raster_layer/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/raster_layer/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/raster_layer/options/" --- ### name _string_ **optional** _default:_ 自动数字编号 设置图层名称,可根据 name 获取 layer ```javascript scene.getLayerByName(name); ``` ### visible _bool_ **optional** _default:_ true 图层是否可见 ### zIndex _int_ **optional** _default:_ 0 图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级 L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中 ### minZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最小缩放等级 ### maxZoom _number_ **optional** _default:_ Mapbox (0-24) 高德 (2-19) 图层显示最大缩放等级 ### autoFit _bool_ **optional** _default:_ false layer 初始化完成之后,地图是否自动缩放到图层范围 ### pickingBuffer _bool_ **optional** _default:_ 0 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围(放大图层对象的尺寸) ### blend _string_ **optional** _default:_ 'normal' 图层元素混合效果 - normal 正常效果 默认 发生遮挡的时候,只会显示前面的图层的颜色 - additive 叠加模式 发生遮挡的时候,显示前后图层颜色的叠加 - subtractive 相减模式 发生遮挡的时候,显示前后图层颜色的相减 - max 最大值 发生遮挡的时候,显示图层颜色 rgb 的最大值 ### enablePropagation _boolean_ **optional** _default:_ 'false' 图层事件,默认只响应最上层图层,设置为true 将允许事件透传 ⚠️ mask、maskfence 不推荐使用,一下配置 2.14.x 之后版本生效 模板图层:用做模板的图层,PointLayer、LineLayer、PolygonLayer 都可以作为模板 掩模图层:被模板切割的图层 ### enableRelativeCoordinates 图层使用相对坐标系,缩放等级大于 20,室内场景 ### maskLayers 掩模图层生效 _array Layer_ **optional** _default:_ [] ### enableMask 掩模图层生效 是否开启掩模,默认开启 maskLayers 不为空时生效 _bool_ **optional** _default:_ true ### maskInside 掩模图层生效 _boolean_ **optional** _default:_ true 用来描述当前图层的内容与掩模边界显示。 - `true` 在掩模内部显示 - `false` 在掩模外部显示 ### maskOpetation 掩模方式 模板图层生效 _枚举_ **optional** _default:_ and maskLayers 为多个时失效,需要在模板图层设置 - or 交集 - and 并集 使用示例 ```ts const polygonLayer = new Polygon(); const rasterLayer = new Raster({ // 栅格图层使用polygon 掩模 maskLayers: [polygonLayer], enableMask: true, maskInside: true, }); ``` #### GeoJSON - Canonical page: https://l7.antv.antgroup.com/zh/api/source/geojson/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/geojson.md - Description: GeoJSON --- title: "GeoJSON" description: "GeoJSON" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/geojson/" --- ## 简介 GeoJSON 是一种对各种地理数据结构进行编码的格式。GeoJSON 对象可以表示几何、特征或者特征集合。GeoJSON 支持下面几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON 里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。 [The GeoJSON Format](https://tools.ietf.org/html/draft-butler-geojson-06) L7 数据 source 支持 传入 Geometry 集合 FeatureCollection ### Feature Collection Object 一个 feature Colletion 由对个 feature 组成 ```json { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "name": "tom" }, "geometry": { "type": "Polygon", "coordinates": [ [ [-2.8125, 34.59704151614417], [65.390625, 34.59704151614417], [65.390625, 61.10078883158897], [-2.8125, 61.10078883158897], [-2.8125, 34.59704151614417] ] ] } } ] } ``` ### Feature Object 一个 feature 有 geometry 空间信息,properties 属性信息,其中 geometry 是必须字段 ```json { "type": "Feature", "properties": {}, "geometry": {} } ``` ### Gemetry Object 支持 Gemetry Object 类型 #### Point ```json { "type": "Point", "coordinates": [100.0, 0.0] } ``` #### MultiPoint ```json { "type": "MultiPoint", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] } ``` Line #### LineSring ```json { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] } ``` #### MultiLineString ```json { "type": "MultiLineString", "coordinates": [ [ [100.0, 0.0], [101.0, 1.0] ], [ [102.0, 2.0], [103.0, 3.0] ] ] } ``` Polygon #### Polygon ```json { "type": "Polygon", "coordinates": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ] } ``` With holes: ```json { "type": "Polygon", "coordinates": [ [ [-170.0, 10.0], [170.0, 10.0], [170.0, -10.0], [-170.0, -10.0], [-170.0, 10.0] ], [ [175.0, 5.0], [-175.0, 5.0], [-175.0, -5.0], [175.0, -5.0], [175.0, 5.0] ] ] } ``` #### MultiPolygon ```json { "type": "MultiPolygon", "coordinates": [ [ [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ] ], [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ] ] ] } ``` [geojson 详细文档](<>) ## GeoJSON 相关的 JS 库 ### 地理统计分析工具 [turfjs](http://turfjs.org/): 地理数据计算,处理,统计,分析的 JavaScript 库 ### 在线工具: [http://geojson.io/](http://geojson.io/) 可以在线查看,绘制,修改 GeoJSON 数据 [https://mapshaper.org/](https://mapshaper.org/) 可以查看较大的 geojson,还能够简化 GeoJSON 数据 #### Options - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/common/options/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/common/options.md - Description: Options --- title: "Options" description: "Options" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/common/options/" --- #### sourceLayer _string_ **required** 只有矢量图层生效,用于设置矢量图层的数据源。 🌟 一般矢量服务返回的数据中存在多个图层的数据,我们需要从中进行选取。 ```javascript const layer = new PointLayer({ sourceLayer: 'city', }); ``` #### featureId _string_ **optional** _default:_ 自动数字编号 只有矢量图层生效,用于指定矢量图层的编码 `id`。 🌟 编码 `id` 用于在图层高亮时使用。 ```javascript const layer = new PointLayer({ featureId: 'id', }); ``` #### Logo 标志 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/logo/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/logo.md - Description: Logo 标志 --- title: "Logo 标志" description: "Logo 标志" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/logo/" --- 用于在地图上展示 Logo 图片的控件,并且支持超链接点击跳转。  ## 说明 当前 L7 会默认在地图左下角展示该控件,如需隐藏可以在 Scene 实例化时配置: ```ts import { Scene } from '@antv/l7'; const scene = new Scene({ // ... // 关闭默认 L7 Logo logoVisible: false, }); ``` ## 使用 [示例](/zh/examples/component/control/logo/) ```ts import { Scene, Logo } from '@antv/l7'; const scene = new Scene({ //... logoVisible: false, }); scene.on('loaded', () => { const logo = new Logo({ // 图片 url img: 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*GRb1TKp4HcMAAAAAAAAAAAAAARQnAQ', // 跳转地址 href: 'https://l7.antv.antgroup.com', }); scene.addControl(logo); }); ``` ## 配置 | 名称 | 说明 | 类型 | | ---- | ---------------------------------------------------- | -------- | | img | Logo 展示的图片 url | `string` | | href | 点击 Logo 跳转的超链接,不传则纯展示图片,点击不跳转 | `string` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### 飞线 - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/flyline/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/flyline.md - Description: 飞线 --- title: "飞线" description: "飞线" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/flyline/" --- 用户在地球模式下使用飞线图层无需做额外的操作,L7 会自动识别地球模式并相关的转化 ## 使用 地球飞线图通过 `LineLayer` 和 `EarthLayer` 实例化 ```javascript import { EarthLayer, LineLayer } from '@antv/l7'; ``` ### shape 地球飞线图层 shape 只支持 **arc3d** #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/source/" --- 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 🌟 热力图的数据使用和点图层保持一致。 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 var data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [120, 30], ... ] }, }, ], }; var layer = new HeatmapLayer() .source(data) ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; var layer = new HeatmapLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30 }, ... ] var layer = new HeatmapLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', } }) ``` #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/image_layer/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/image_layer/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/image_layer/source/" --- `imagelayer` 通过提供在线图片的 `url` 指定数据,通过 `extent` 指定图片在地图上的矩形范围的位置。 ```js layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` 也可通过 `coordinates` 指定一系列坐,来定义图片在地图上的不规则形状范围的位置。 ```js layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', coordinates: [ [100.959388, 41.619522], [101.229887, 41.572654], [101.16971, 41.377836], [100.900015, 41.424628], ], }, }); ``` #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/source/" --- 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 const data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'LineString', coordinates: [ [106.5234375, 57.51582286553883], [136.40625, 61.77312286453146], ], }, }, ], }; const layer = new LineLayer().source(data); ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; new LineLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30, lng1: 125, lat1: 30 }, ... ] var layer = new LineLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', x1: 'lng1', y1: 'lat1' } }) ``` #### 百度地图 - Canonical page: https://l7.antv.antgroup.com/zh/api/map/bmap/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/bmap.md - Description: 百度地图 --- title: "百度地图" description: "百度地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/bmap/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 L7 目前支持的百度地图是[API GL版本](https://lbsyun.baidu.com/index.php?title=jspopularGL),也是百度地图官方推荐使用版本。 ### 申请token 使用百度地图之前,需要申请百度地图密钥,如何申请百度地图密钥[点我查看](https://lbs.baidu.com/index.php?title=jspopularGL/guide/getkey)。 ⚠️ L7 内部设置了默认 token,仅供测试使用 ### import ```javascript import { BaiduMap } from '@antv/l7-maps'; ``` ### 实例化 L7 提供 BaiduMap直接实例化地图,也可外部传入方式实例化地图。 新项目推荐 BaiduMap 直接实例化,已有地图项目可外部传入方式,以便快速接入 L7 的能力。 #### BaiduMap 实例化 ```js import { BaiduMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new BaiduMap({ // 填写百度地图密钥,此为测试token,不可用于生产 token: 'zLhopYPPERGtpGOgimcdKcCimGRyyIsh', center: [103, 30], pitch: 4, zoom: 10, rotation: 19, }), }); ``` #### 外部传入实例化 ⚠️ scene id 参数需要与 BMapGL.Map 实例是同个容器。 ⚠️ 传入地图实例需要自行引入[百度地图的 API](https://lbs.baidu.com/index.php?title=jspopularGL/guide/show) ```javascript const map = new BMapGL.Map('map', { zoom: 11, // 初始化地图层级 minZoom: 4, maxZoom: 23, enableWheelZoom: true, }); const scene = new Scene({ id: 'map', map: new BaiduMap({ mapInstance: map, }), }); ``` BaiduMap [示例地址](#baidumap-实例化)、外部传入[示例地址](#外部传入实例化) ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### CanvasLayer - Canonical page: https://l7.antv.antgroup.com/zh/api/other/canvas/ - Markdown source: https://l7.antv.antgroup.com/zh/api/other/canvas.md - Description: CanvasLayer --- title: "CanvasLayer" description: "CanvasLayer" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/other/canvas/" --- `CanvasLayer` 会在官方图层画布之上额外创建一个 `canvas` 画布,允许用户通过 `canvas` 绘制的方法自定义图层的内容和样式,相比于 `Marker` 通过创建实际 `DOM` 的方式,`CanvasLayer` 无疑有更佳的性能,同时 `CanvasLayer` 的绘制内容会永远覆盖在官方图层的内容之上。 用户主要通过 `CanvasLayer` 的 `draw` 回调函数来自定义 `canvas` 上绘制的内容,并且 `CanvasLayer` 在用户进行地图缩放、移动等操作时会自动调用 `draw` 方法保证绘制物与地图位置相对不变。 ## 使用 ```jsx import { CanvasLayer, Scene } from '@antv/l7'; const scene = new Scene({ //... }); scene.on('loaded', () => { const layer = new CanvasLayer({ trigger: 'change', }); layer.draw(({ container, ctx, utils }) => { const [width, height] = size; // 清空画布 ctx.clearRect(0, 0, container.width, container.height); // 经纬度 => 像素坐标 的转换 const { x, y } = utils.lngLatToContainer([120, 30]); // 设置绘制颜色 ctx.fillStyle = 'red'; // 绘制一个矩形 ctx.fillRect(x, y, 10, 10); }); scene.addLayer(layer); }); ``` [在线案例](/zh/examples/point/chart/custom/) ### 属性 #### draw 类型:`(drawParams: ICanvasLayerRenderParams) => void` ```TypeScript type ICanvasLayerRenderParams = { canvas: HTMLCanvasELement; ctx: RenderingContext; container: { width: number; height: number; bounds: [ [number, number], [number, number], ]; }; utils: { lngLatToContainer: IMapService['lngLatToContainer']; }; mapService: IMapService; } ``` 作用:`draw` 方法是用于在地图状态更新时调用的渲染函数,接受相关参数,用户在该函数中写 canvas 的绘制逻辑 - canvas CanvasLayer 生成的 canvas DOM 节点 - ctx 生成的 canvas DOM 的上下文 - container 当前视图的实际绘图范围和地图展示的经纬度范围 - utils 提供在 `draw` 方法中常用的工具函数 - mapService 当前地图的 `mapService`,提供位置转换的相关方法 #### trigger 类型:`'change' | 'end'` 作用:指定 CanvasLayer 的更新方式,update 有两个值 'change'、'end',默认为 'change' - change:地图更新时触发 `draw` 方法 - end: 地图拖动完后/缩放完后触发 `draw` 方法 #### zIndex 类型:`number` 作用:每个创建一个 CanvasLayer,L7 会生成一个 Canvas DOM 的实例,我们通过设置 zIndex 的值来调整 CanvasLayer 的层级。 ### 方法 #### draw 类型:`(drawCallback: (renderParams: ICanvasLayerRenderParams) => void) => this` 作用:更新 draw 绘制方法 #### updateLayerConfig 类型:`(options: Partial) => this` 作用:更新 `CanvasLayer` 的配置 #### render 类型:`() => void` 作用:触发 CanvasLayer 的重新渲染 #### getCanvas 类型:`() => HTMLCanvasElement | null` 作用:获取 `Canvas` 实例,只有在 `CanvasLayer` 的 `add` 事件触发后,`getCanvas` 才能获取到值 #### show 类型:`() => this` 作用:显示 `CanvasLayer` #### hide 类型:`() => this` 作用:隐藏 `CanvasLayer` ### 事件 图层基础事件可见 [图层事件](/zh/api/base_layer/base#图层事件) **注意**:如需监听 `canvas` 画布相关事件,需要在 `CanvasLayer` 触发 `add` 事件后(`canvas` DOM 初始化并挂载完成后),方可监听相应事件。 例如: ```jsx const layer = new CanvasLayer({ // ... }); scene.addLayer(layer); layer.on('add', () => { // 通过 getCanvas 获取 canvas DOM 实例 layer.getCanvas().addEventListener('click', (e) => { console.log(e); }); }); ``` #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/source/" --- 图层数据使用经纬度格式,数据源支持 JSON、GeoJSON、CSV 三种数据格式。 - [GeoJSON](/zh/api/source/geojson/#point) - [CSV](/zh/api/source/csv/#parser) - [JSON](/zh/api/source/json/#点数据) 🌟 通常每种数据都需要相应的 parser 解析数据 ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 var data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [120, 30], ... ] }, }, ], }; var layer = new PointLayer() .source(data) ``` ### CSV ```js // 传入 txt 类型数据 var data = `from,to,value,type,lng1,lat1,lng2,lat2 鎷夎惃,娴疯タ,6.91,move_out,91.111891,29.662557,97.342625,37.373799 鎷夎惃,鎴愰兘,4.79,move_out,91.111891,29.662557,104.067923,30.679943 鎷夎惃,閲嶅簡,2.41,move_out,91.111891,29.662557,106.530635,29.544606 鎷夎惃,鍖椾含,2.05,move_out,91.111891,29.662557,116.395645,39.929986 ...`; var layer = new PointLayer().source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', }, }); ``` ### JSON ```js // 传入 JSON 类型的数据 var data = [ { lng: 120, lat: 30 }, ... ] var layer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', } }) ``` #### Source - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/source/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/source.md - Description: Source --- title: "Source" description: "Source" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/source/" --- 几何体图层数据推荐使用 GeoJSON 格式的数据。 - [GeoJSON](/zh/api/source/geojson/#point) ### GeoJSON ```js // 传入 GeoJSON 类型数据 *** L7 默认支持,不需要 parser 解析 const data = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [104.4140625, 35.460669951495305], [98.7890625, 24.206889622398023], [111.796875, 27.371767300523047], [104.4140625, 35.460669951495305], ], ], }, }, ], }; const layer = new PolygonLayer().source(data); ``` #### Raster Data - Canonical page: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_data/ - Markdown source: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_data.md - Description: Raster Data --- title: "Raster Data" description: "Raster Data" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/raster_layer/raster_data/" --- ## 简介 单波段栅格数据渲染、根据栅格数据进行可视化着色 ## source Raster data 数据栅格的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图、植被分布图和夜光图。 - data 数据 - option 配置项 - parser 数据解析参数 ### data data 解析后的数据,为数组 ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` 以 geotiff 为例需要先将数据解析出来,作为 data 输入给 source ```tsx import * as GeoTIFF from 'geotiff'; async function getTiffData() { async function getTiffData() { const response = await fetch( 'https://gw.alipayobjects.com/zos/antvdemo/assets/light_clip/lightF182013.tiff', ); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { data: values[0], width, height, }; } } const tiffdata = await getTiffData(); layer.source(tiffdata.data, { parser: { type: 'raster', width: tiffdata.width, height: tiffdata.height, extent: [73.4821902409999979, 3.8150178409999995, 135.1066187319999869, 57.6300459959999998], }, }); ``` ### parser - type: raster - extent: 栅格的经纬度范围 [minlng, minlat,maxLng, maxLat] - width 数据宽度 - height 数据高度 根据栅格数据的经纬度范围,将其添加到地图上。 ```javascript layer.source(rasterData, { parser: { type: 'raster', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` ### 完整示例 [Raster ndi](../../../../examples/raster/data/#dem) ## style `style` 方法用于配制图层的样式, - 单通道 绘制结果由是单一的数值控制,如灰度图,数值对应的颜色可以通过表示配置 `rampColors` 色带控制。 ```js layer.style({ opacity: 0.5, }); ``` ### 配置 | style | 类型 | 描述 | 默认值 | | ----------- | ------------------ | ------------------------------------------- | ------------- | | opacity | `number` | 图形的透明度 | `1` | | clampLow | `boolean` | 设置为 `true`,低于 `domain` 的数据将不显示 | `false` | | clampHigh | `boolean` | 设置为 `true`,高于 `domain` 的数据将不显示 | `false` | | domain | `[number, number]` | 数据映射区间 | `[ 0, 8000 ]` | | noDataValue | `number` | 不会显示的值 | `-9999999` | | rampColors | `IRampColors` | 值域映射颜色的色带 | `/` | ### rampColors 颜色色带 - type 类型 支持 `linear','quantize','custom','cat' - colors 颜色数组 - positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值 ⚠️ 2.13 新增特性 #### cat 枚举类型色带 枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举 ```tsx { type:'cat', colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'], positions:[1,20,101,102,200], } ``` #### quantize 等间距分类色带 等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。 等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数 ```tsx rampColors: { type:'quantize', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'] } ``` #### linear 线性连续色带 linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1 ```tsx rampColors: { type:'linear', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions [0,200,1000,4000,8000] } ⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。 ``` #### custom 自定义分段色带 自定义分段色带区别等间距色带,用户自定义分段间隔。 自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions ```tsx rampColors: { type:'custom', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions: [0,200,1000,4000,8000,10000] } ``` #### JSON - Canonical page: https://l7.antv.antgroup.com/zh/api/source/json/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/json.md - Description: JSON --- title: "JSON" description: "JSON" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/json/" --- GeoJSON 虽然是通用的的地理数据格式,在具体使用场景中,数据服务人员可能并不熟悉 GeoJSON,或者没有生成 GeoJSON 的工具, 因此 L7 对数据定义了 Parser 的概念,你的数据可以是任何格式,使用指定数据对应的地理信息字段即可。 ## JSON ⚠️ json 不是标准的地理数据结构,因此在使用时务必要设置 Parser json 数据解析使用对应 JSON parser ## parser 支持两种解析方式 ### 简易解析方式 该方式只支持解析的点数据,或者只有两个点的线段,或者弧线数据 - type `string` 必选 `json` - x `string` 点数据表示 经度 - y `string` 点数据表示 纬度 - x1 `string` 经度 - x2 `string` 纬度 如果数据是点数据,只需要设置 x,y 字段即可 如果是线段、弧线数据,需要知道起止点坐标,x,y,x1,y1 ```javascript layer.source(data, { parser: { type: 'json', x: 'lng', y: 'lat', }, }); ``` [JOSN 数据 demo 示例](/zh/examples/gallery/animate/animate-path-texture/) ### 通用解析方式 可也解析任意复杂的点,线面 - type `string` 必选 `json` - coordinates `array` 必选,主要用于表达比较复杂的格式,等同于 geojson coordinates 属性 ```javascript layer.source(data, { parser: { type: 'json', coordinates: 'coord', }, }); ``` ## 使用示例 ### 点数据 #### 简易解析 - type json - x: 经度字段 - y: 纬度字段 ```javascript const data = [ { lng: 112.345, lat: 30.455, value: 10, }, { lng: 114.345, lat: 31.455, value: 10, }, ]; layer.source(data, { parser: { type: 'json', x: 'lng', y: 'lat', }, }); ``` #### 通用解析 [ 点 coodinates 数据格式](/zh/api/source/geojson##point) ```javascript const data = [ { coord: [112.345, 30.455], value: 10, }, { coord: [114.345, 32.455], value: 10, }, ]; layer.source(data, { parser: { type: 'json', coordinates: 'coord', }, }); ``` ### 线数据 #### 简易解析 - type: json - x `string` 经度 - y `string` 纬度 - x1 `string` 经度 - x2 `string` 纬度 简易解析只支持两个点组成的线段,主要再绘制弧线的时候比较常用,只需指定线段的起止点坐标 ```javascript const data = [ { lng1: 112.345, lat1: 30.455, lng2: 112.345, lat2: 30.455, value: 10, }, { lng1: 114.345, lat1: 31.455, lng2: 112.345, lat2: 30.455, value: 10, }, ]; layer.source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng1', y1: 'lat2', }, }); ``` #### 通用解析 绘制线段、弧线也支持使用 coordinates 组织数据 coordinates 包含两个坐标, 第一个坐标 对应 x, y 第二个坐标 对应 x1, y1 ```javascript const data = [ { id: '1', coord: [ [101.953125, 50.51342652633956], [119.17968749999999, 33.137551192346145], ], }, ]; layer.source(data, { parser: { type: 'json', coordinates: 'coord', }, }); ``` 如果需要使用绘制轨迹数据,需要通过 coodinates 指定线的点序列。 coordinate 格式 geojson 的 coordinate 字段 支持 LineString, MultiLineString [ 线 coodinates 数据格式](/zh/api/source/geojson#linesring) ```javascript const data = [ { name: 'path1', path: [ [58.00781249999999, 32.84267363195431], [85.78125, 25.16517336866393], [101.953125, 41.77131167976407], [114.9609375, 39.639537564366684], [117.42187500000001, 28.613459424004414], ], }, ]; ``` 使用时通过 coordinates 指定 ```javascript layer.source(data, { parser: { type: 'json', coordinates: 'path', }, }); ``` ### 面数据 面数据 coordinates 字段比较复杂不支持简易的解析方式 #### 通用解析 需要指定 coordinates 字段, 格式同 GeoJSON 的 coordinates 字段 [面 coodinates 数据格式](/zh/api/source/geojson/#polygon) **注意面数据 coord 是三层数据结构** ```javascript [ { type: 'Polygon', geometryCoord: [ [ [115.1806640625, 30.637912028341123], [114.9609375, 29.152161283318915], [117.79541015625001, 27.430289738862594], [118.740234375, 29.420460341013133], [117.46582031249999, 31.50362930577303], [115.1806640625, 30.637912028341123], ], ], }, ]; layer.source(data, { parser: { type: 'json', coordinates: 'geometryCoord', }, }); ``` #### Marker 标注 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/marker/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/marker.md - Description: Marker 标注 --- title: "Marker 标注" description: "Marker 标注" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/marker/" --- Marker 地图标注 目前只支持 2D DOM 标注 ## 构造函数 Marker `const Marker = new L7.Marker(option)` #### option - color `string`  设置默认 marker 的颜色 - element `DOM|string` 自定义 marker DOM 节点,可以是 dom 实例,也可以是 dom id - anchor `string` 锚点位置 支持 center, top, top-left, top-right, bottom, bottom-left,bottom-right,left, right - offsets `Array` 偏移量 [ 0, 0 ] 分别表示 X, Y 的偏移量 - overflowHide `boolean` 超出屏幕时是否隐藏 Marker,默认为 true - draggable `boolean` 是否支持拖拽调整 Marker 位置 - extData 用户自定义属性,支持任意数据类型,存储 marker 属性信息 ### 添加到 Scene ```javascript scene.addMarker(marker); ``` ## 方法 #### setLnglat(lngLat: ILngLat | [number, number]) 设置 marker 经纬度位置 ```javascript marker.setLnglat({ lng: 120, lat: 30 }); // 或数组形式 marker.setLnglat([120, 30]); ``` #### getLngLat(): ILngLat 获取 marker 经纬度坐标 ```javascript const { lng, lat } = marker.getLngLat(); ``` #### remove() 移除 marker,从地图上删除并释放事件绑定 ```javascript marker.remove(); ``` #### hide() 隐藏 marker,不从地图中删除,可通过 `show()` 恢复显示 ```javascript marker.hide(); ``` #### show() 显示已隐藏的 marker ```javascript marker.show(); ``` #### getElement(): HTMLElement 获取 marker 的 DOM 元素 ```javascript const el = marker.getElement(); ``` #### setElement(element: HTMLElement) 设置 marker 的 DOM 元素,通过此方法可更新 Marker 样式 ```javascript const el = document.createElement('div'); marker.setElement(el); ``` #### getOffset(): number[] 获取 marker 的偏移量 `[x, y]` ```javascript const [x, y] = marker.getOffset(); ``` #### setDraggable(draggable: boolean) 设置是否支持拖拽调整位置 ```javascript marker.setDraggable(true); ``` #### getDraggable(): boolean 获取当前是否支持拖拽调整位置 ```javascript const draggable = marker.getDraggable(); ``` #### togglePopup() 开启或者关闭 marker 弹出框 #### openPopup() 打开关联的 Popup ```javascript marker.openPopup(); ``` #### closePopup() 关闭关联的 Popup ```javascript marker.closePopup(); ``` #### setPopup(popup: Popup) 为 marker 设置 popup ```javascript const popup = new Popup({ anchor: 'left' }).setText('Hello'); marker.setPopup(popup); ``` #### getPopup(): Popup 获取 marker 关联的 popup ```javascript const popup = marker.getPopup(); ``` #### getExtData(): any 获取用户自定义数据 ```javascript const data = marker.getExtData(); ``` #### setExtData(data: any) 设置用户自定义数据 ```javascript marker.setExtData({ name: 'test', value: 42 }); ``` ## 示例代码 #### 默认 Marker `const marker = new L7.Marker({color:'blue'})` #### 自定义 Marker ```javascript var el = document.createElement('label'); el.className = 'labelclass'; el.textContent = data[i].v; el.style.background = getColor(data[i].v); const marker = new L7.Marker({ element: el, }).setLnglat([data[i].x * 1, data[i].y]); scene.addMarker(marker); ``` #### 设置 popup ```javascript var popup = new L7.Popup({ anchor: 'left', }).setText(item.name); new L7.Marker({ element: el, }) .setLnglat(item.coordinates) .setPopup(popup); ``` ## 事件 ### 鼠标事件 - mousemove - click - mousedown - mouseup - dblclick - contextmenu - mouseover - mouseout - dragstart - dragging - dragend 事件返回数据 - target 事件触发源 - data extData 用户自定义数据 - lnglat marker 经纬度 ```javascript marker.on('click', (e) => {}); ``` ## demo 地址 [demo1](/zh/examples/tutorial/marker/amap/) #### Marker 图层 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/marker_layer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/marker_layer.md - Description: Marker 图层 --- title: "Marker 图层" description: "Marker 图层" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/marker_layer/" --- MarkerLayer 是 Marker 的升级版,Marker 是独立的地图标注,MarkerLayer 则是统一管理大量的 Marker 数据。 **技术差异** - Marker DOM 绘制一个地图元素 - MarkerLayer 统一管理多个 DomMarker - PointLayer 通过 WebGL 绘制元素。 **功能差异** - MarkerLayer 元素的自定义性比较强,任何 HTML+ CSS 的组合都可以绘制在地图上。 - PointLayer 自定义性比较弱,实现成本比较高,优势可以绘制大量的数据,性能比较好。 ## 使用 ```javascript import { Marker, MarkerLayer } from '@antv/l7'; ``` ### 构造函数 ```javascript const markerLayer = new MarkerLayer(option); // 调用 addMarker方法 将多个Marker添加到Layer scene.addMarkerLayer(markerLayer); ``` #### option - cluster 聚合 `boolean` 默认 `false` - clusterOption 聚合配置 - field `string` 聚合统计字段 - method `sum| max| min| mean` - radius 聚合半径 number default 40 - minZoom: 最小聚合缩放等级 number default 0 - maxZoom: 最大聚合缩放等级 number default 16 - element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素 回调函数包含以下参数 - point_count 默认 聚合元素个数 - clusterData `Array` 聚合节点的原始数据 - point_sum 聚合求和 根据 field 和 method 计算 - point_max 聚合最大值 根据 field 和 method 计算 - point_min 聚合最小值 根据 field 和 method 计算 - point_mean 聚合平均值 根据 field 和 method 计算 - markerOption 图层默认 Marker 配置(新增) - color `string` 默认标记颜色,会尝试设置到 marker 内的 svg path fill 或作为背景色 - style `object` CSS 样式对象,会应用到 marker 的容器元素上(例如 width/height/borderRadius) - className `string` 额外的 class 名称,会加入到 marker 的 DOM 元素上 示例:统一设置图层内 marker 的默认样式 ```javascript const markerLayer = new MarkerLayer({ cluster: true, markerOption: { color: '#ff5722', style: { width: '28px', height: '28px', borderRadius: '50%' }, className: 'demo-marker-default', }, }); ``` 说明:单个 Marker 如果在构造时传入了自定义 `element` 或 `style`,以单个 Marker 的配置为准,`markerOption` 仅在没有显式样式时作为默认值应用。 #### extData 与聚合数据 当你向 `MarkerLayer` 添加 Marker 时,可通过 `Marker` 的 `extData` 属性传入业务数据,这对于使用 `clusterOption.field/method` 做统计非常重要。 示例:为每个 Marker 设置业务数据 ```javascript const marker = new Marker({ extData: nodes.features[i].properties, }).setLnglat({ lng: x, lat: y }); markerLayer.addMarker(marker); ``` 在聚合逻辑中,`MarkerLayer` 为生成的聚合 Marker 也会把 supercluster 返回的 `feature.properties` 复制到聚合 Marker 的 `extData` 上。因此当你执行: ```javascript scene.addMarkerLayer(markerLayer); const maps = markerLayer.getMarkers().map((item) => item.getExtData()); console.log(maps); ``` 你将会得到每个 Marker(或聚合 Marker)对应的 `extData`,不会再看到 `undefined`。 此外,当某个聚合包含仅 1 个原始点时,`MarkerLayer` 会优先显示该原始 Marker(并保留其 `extData`),以保证单点场景下保留原始样式与数据。 --- English (API) ## MarkerLayer (summary) MarkerLayer manages multiple DOM-based Markers on the map and provides clustering support via supercluster. It offers more flexibility for custom HTML/CSS markers compared to WebGL-based PointLayer. ### Options (new) - markerOption: optional defaults applied to markers added to this layer - color: string — default marker color; will try to set SVG fill or fallback to background color - style: object — CSS style object applied to the marker element (e.g. width/height/borderRadius) - className: string — additional class name to add to marker DOM element Example: ```javascript const markerLayer = new MarkerLayer({ cluster: true, markerOption: { color: '#ff5722', style: { width: '28px', height: '28px', borderRadius: '50%' }, className: 'demo-marker-default', }, }); ``` ### extData and clustering Each Marker may carry business data via `extData` (used by cluster statistics when `clusterOption.field/method` are set). `MarkerLayer` also attaches the supercluster `feature.properties` to cluster markers' `extData` so `marker.getExtData()` returns useful info for both single markers and clusters. When a cluster contains only 1 original point, `MarkerLayer` will prefer to show the original marker (preserving its element/style/extData) instead of rendering a cluster element. ### 方法 #### addMarker 参数 - marker `IMarker` 需要添加的 Marker 添加 Marker 通过 Marker 对象实例化一个 Marker ```javascript const marker = new Marker().setLnglat(); // 添加进Marker必须设置经纬度才能添加 markerLayer.addMarker(marker); ``` 为 Marker 添加属性信息, 如果聚合参数设置统计配置项 `field| method`需要为 Marker 添加属性信息 通过 Marker 的 extData[配置项](/zh/api/component/marker#option)设置 Marker 属性信息 ```javascript const marker = new Marker({ extData: nodes.features[i].properties, }).setLnglat({ lng: coordinates[0], lat: coordinates[1], }); ``` #### removeMarker 从 MarkerLayer 移除 Marker 说明:调用 `markerLayer.removeMarker(marker)` 会执行 Marker 的清理逻辑(从场景 DOM 中移除、解绑事件等),并同步更新内部聚合索引。如果需要临时隐藏 Marker,请使用下面的 `hide()`/`show()` 方法,而不是反复 `remove`/`add`,以保留 Marker 的 extData 与状态。 示例: ```javascript // 从图层移除并销毁 marker markerLayer.removeMarker(marker); // 仅隐藏(不销毁)marker marker.hide(); // 恢复显示 marker.show(); ``` #### getMarkers 获取 MarkerLayer 中的所有 Marker #### clear 清除掉所有的 Marker #### hide / show(Marker) 每个 `Marker` 实例现在提供 `hide()` 与 `show()` 方法,用于在不移除数据和 DOM 绑定的情况下控制显示状态。隐藏后,Marker 不会参与后续的位置更新渲染(例如缩放/平移期间),但其 `extData` 与其他状态将被保留。此方法适合临时控制可见性或实现按需渲染。 示例: ```javascript // 隐藏图层内的单个 marker const [m] = markerLayer.getMarkers(); m.hide(); // 稍后恢复 m.show(); ``` 说明:`MarkerLayer` 的 `addMarker` 会在图层已加入场景后,立即把新 Marker 添加到场景 DOM 中;如果图层尚未 add 到 Scene,则会在 `scene.addMarkerLayer(layer)` 时集中挂载。图层级别的 `markerOption` 会作为默认值应用到每个新增 Marker,只有当 Marker 自身显式提供 `element` / `style` 时,才会覆盖这些默认值。 #### ### Scene #### addMarkerLayer 添加 MarkerLayer ```javascript scene.addMarkerLayer(layer); ``` #### removeMarkerLayer 移除 MarkerLayer ```javascript scene.removeMarkerLayer(layer); ``` ### demo 地址 [markerLayer ](/zh/examples/component/marker/markerlayer/) [markerLayer 聚合](/zh/examples/component/marker/clustermarker/) #### Zoom 缩放 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/zoom/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/zoom.md - Description: Zoom 缩放 --- title: "Zoom 缩放" description: "Zoom 缩放" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/zoom/" --- 用于控制地图**放大**和**缩小**的控件,并且当地图达到最大或最小缩放比时,会禁用对应缩放按钮。 ## 使用 [示例](/zh/examples/component/control/zoom/) ```ts import { Scene, Zoom } from '@antv/l7'; const scene = new Scene({ //... }); scene.on('loaded', () => { const zoom = new Zoom({ zoomInTitle: '放大', zoomOutTitle: '缩小', }); scene.addControl(zoom); }); ``` ## 配置 | 名称 | 说明 | 类型 | | ------------ | -------------------------------------------- | --------------------- | | zoomInText | 放大按钮的展示内容 | `Element` \| `string` | | zoomInTitle | 放大按钮的 `title` 属性 | `string` | | zoomOutText | 缩小按钮的展示内容 | `Element` \| `string` | | zoomOutTitle | 缩小按钮的 `title` 属性 | `string` | | showZoom | 是否展示地图当前实时 zoom 数值,默认向下取整 | `boolean` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------- | -------- | ------------ | | zoomIn | 放大地图 | `() => void` | | zoomOut | 缩小底图 | `() => void` | | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### 点图层 - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/point/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/point.md - Description: 点图层 --- title: "点图层" description: "点图层" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/point/" --- 用户在地球模式下使用点图层无需做额外的操作,L7 会自动识别地球模式并相关的转化 ## 使用 地球点图层通过 `PointLayer` 和 `EarthLayer` 实例化 ```javascript import { PointLayer, EarthLayer } from '@antv/l7'; ``` #### threejs 引擎兼容 - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/three/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/three.md - Description: threejs 引擎兼容 --- title: "threejs 引擎兼容" description: "threejs 引擎兼容" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/three/" --- ## 简介 1、L7 支持允许用户接入第三方的渲染引擎对地图场景进行开发,threejs 作为当前最广泛使用的通用 3D 渲染引擎,L7 将其集成后可以满足 用户自定义开发的需求,可以让 L7 覆盖更多的应用场景。 2、目前 L7Three 模块为了抹平不同地图底图之间的差异,提供了一些兼容方法,如 setMeshScale 方法,通过这些方法用户可以在不同的底图 环境中使用同一套代码。 3、L7 提供的适配方法只负责 threejs 世界坐标到不同地图底图坐标的转化、 gl 上下文的共享以及渲染帧的同步,其余关于 3D 场景内容的搭建 与普通 threejs 应用的开发没有任何区别。 4、L7 本身并没有集成 threejs,所以用于在使用 L7Three 模块的时候需要独立安装 threejs。 ✨ 目前 L7 官方提供的 threejs 兼容支持 Three.js r163+ 版本。 ⚠️ **重要**:Three.js r163+ 版本仅支持 WebGL 2,因此需要在创建 Scene 时配置 `renderer: 'device'` 以启用 WebGL 2 上下文: ```javascript const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'dark', center: [121.4, 31.2], zoom: 14 }), renderer: 'device', // 必须使用 'device' 渲染器以启用 WebGL 2 }); ``` ## 使用 ```javascript // 1、引入对应模块 import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import * as THREE from 'three'; ... // 2、注册服务 scene.registerRenderService(ThreeRender); ... // 3、构建 threejs 图层对象并在其中添加 threejs 构建的网格对象 const threeJSLayer = new ThreeLayer({ onAddMeshes: (threeScene: THREE.Scene, layer: ThreeLayer) => { threeScene.add(new THREE.AmbientLight(0xffffff)); const sunlight = new THREE.DirectionalLight(0xffffff, 0.25); sunlight.position.set(0, 80000000, 100000000); sunlight.matrixWorldNeedsUpdate = true; threeScene.add(sunlight); let center = scene.getCenter(); let cubeGeometry = new THREE.BoxBufferGeometry(10000, 10000, 10000); let cubeMaterial = new THREE.MeshNormalMaterial(); let cube = new THREE.Mesh(cubeGeometry, cubeMaterial); layer.setObjectLngLat(cube, [center.lng + 0.05, center.lat], 0); threeScene.add(cube); }, }) .source(data) .animate(true); // 4、添加 threejs 图层对象 scene.addLayer(threeJSLayer); ``` L7 将 threejs 的引用封装成一个特殊的图层对象,在使用上与其他的图层相同。 ## 构造函数 new ThreeLayer ### onAddMeshes 该方法接受两个参数 threeScene: THREE.Scene, layer: ThreeLayer - threeScene: 这是普通的 threejs 场景对象 - layer: 这是 L7 提供的 threeLayer 对象,上面挂载了 threejs 空间适配到地图空间所需要的方法 ## ThreeLayer 用户新建的图层对象,同时也会在 onAddMesh 方法的第二个参数返回。 以下是挂载在 ThreeLayer 实例上的适配方法。 ### getModelMatrix(lnglat, altitude, rotation, scale): Matrix - lnglat: [number, number] 经纬度 - altitude: number = 0 相对高度 - rotation: [number, number, number] = [0, 0, 0] 旋转角度 - scale: [number, number, number] = [1, 1, 1] 缩放比例 用户可以通过该方法计算在对应经纬度点位、相对高度、旋转角度和缩放的模型矩阵 该方法的返回值是 THREE.Matrix4 类型的矩阵 ### applyObjectLngLat(object, lnglat, altibute): void - object: Object3D threejs 对象 - lnglat: ILngLat[number, number] 经纬度 - altitude = 0 相对高度 用户可以通过该方法将 object 对象从当前位置向指定位置移动(地图经纬度坐标) ### setObjectLngLat(object, lnglat, altibute): void - object: Object3D threejs 对象 - lnglat: ILngLat[number, number] 经纬度 - altitude = 0 相对高度 用户可以通过该方法设置 object 对象的位置(地图经纬度坐标) ### lnglatToCoord(lnglat): [number, number] - lnglat: ILngLat[number, number] 经纬度 用户可以通过该方法将经纬度坐标转化成 threejs 世界坐标 ### adjustMeshToMap(object): void - object: Object3D threejs 对象 用户在添加 threejs 对象的前可以通过该方法调整 3D 对象的姿态,保证添加对象能正确显示 ✨ 在 threejs 世界坐标中,默认的上方向为 Y 轴正方向,而在地图坐标中,默认的上方向为 Z 轴正方向 ✨ 用户不一定使用该方法调整物体的姿态,也可以自己实现 ### setMeshScale(object, x, y, z): void - object: Object3D threejs 对象 - x: number = 1 x 轴方向的缩放比例 - y: number = 1 y 轴方向的缩放比例 - z: number = 1 z 轴方向的缩放比例 用户可以通过该方法设置 threejs 对象缩放 ✨ 其实通过设置 threejs 对象的 scale 属性一样能达到同样的效果,但是由于 mapbox 在计算模型矩阵的时候引入了特殊计算,所以无法直接设置 scale 属性进行缩放 ✨ 同样的,可以直接修改 threejs 的 position、rotation 等调整 3D 对象的姿态 ### addAnimateMixer(mixer): void - mixer: AnimationMixer threejs 的动画混合器 用户通过该方法管理加载模型的动画 ### getRenderCamera(): THREE.Camera 返回根据当前地图场景参数下对应的 THREEJS 相机 ## 加载模型 用户可以使用 threejs 提供的能力加载其支持的任意模型 ### 简单案例 ✨ 以加载 gltf 模型为例 ```javascript // 1、引入加载器 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; ... const threeJSLayer = new ThreeLayer({ onAddMeshes: (threeScene: THREE.Scene, layer: ThreeLayer) => { ... // 2、构建加载器 const loader = new GLTFLoader(); // 3、加载模型 loader.load('https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf', (gltf) => { const model = gltf.scene; layer.adjustMeshToMap(model); layer.setMeshScale(model, 1000, 1000, 1000); layer.setObjectLngLat( model, [center.lng, center.lat], 0 ); // 4、播放模型上绑定的动画 const animations = gltf.animations; if (animations && animations.length) { const mixer = new THREE.AnimationMixer(model); const animation = animations[2]; const action = mixer.clipAction(animation); action.play(); // 5、由 L7 控制模型动画的播放 layer.addAnimateMixer(mixer); } }) } }).source(data) .animate(true) // 若需要播放模型动画,请开启动画模式(或者场景中已经存在开启动画的图层) ``` #### Shape - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/shape/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/shape.md - Description: Shape --- title: "Shape" description: "Shape" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/shape/" --- `shape` 方法用于指定热力图层绘制热力的类型,支持经典热力、蜂窝热力、网格热力等多种类型。 ```js layer.shape('heatmap'); ``` | shape 值 | 说明 | | ---------------- | ---------------------------------- | | `heatmap` | 2D 经典高斯热力图 | | `heatmap3D` | 3D 热力图,在 Z 轴方向展示热力强度 | | `hexagon` | 六边形网格(2D 平面) | | `hexagonColumn` | 六边形柱状网格(3D 拉伸) | | `square` | 正方形网格(2D 平面) | | `squareColumn` | 正方形柱状网格(3D 拉伸) | | `triangle` | 三角形网格(2D 平面) | | `triangleColumn` | 三角形柱状网格(3D 拉伸) | | `cylinder` | 圆柱聚合(3D 拉伸) | ### shape('heatmap') `shape` 为 `heatmap` 时,绘制 2D 经典高斯热力图,通过颜色渐变反映数据密度。 ### shape('heatmap3D') `shape` 为 `heatmap3D` 时,绘制 3D 热力图,在 Z 轴方向通过高度反映热力强度,需开启地图的 3D 视角。 ### shape('hexagon') / shape('hexagonColumn') 基于六边形网格的聚合热力,`hexagon` 为 2D 填充,`hexagonColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'hexagon'` 使用。 ### shape('square') / shape('squareColumn') 基于正方形网格的聚合热力,`square` 为 2D 填充,`squareColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'square'` 使用。 ### shape('triangle') / shape('triangleColumn') 基于三角形网格的聚合热力,`triangle` 为 2D 填充,`triangleColumn` 为 3D 柱状拉伸。需配合 `transforms` 中 `type: 'triangle'` 使用。 ### shape('cylinder') 基于圆形网格的聚合热力,以 3D 圆柱形式展示。需配合 `transforms` 中 `type: 'grid'` 使用。 ### transforms 网格热力和蜂窝热力的实现依赖配置 `transforms` 的参数,[具体说明使用](/zh/api/source/source/#transforms)。 ```js fetch('https://gw.alipayobjects.com/os/basement_prod/513add53-dcb2-4295-8860-9e7aa5236699.json') .then((res) => res.json()) .then((data) => { const layer = new HeatmapLayer({}) .source(data, { transforms: [ { type: 'hexagon', size: 100, field: 'h12', method: 'sum', }, ], }) .size('sum', [0, 600]) .shape('hexagonColumn') .style({ coverage: 0.8, angle: 0, }) .color( 'sum', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#CEF8D6', ].reverse(), ); scene.addLayer(layer); }); ``` #### Shape - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/shape/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/shape.md - Description: Shape --- title: "Shape" description: "Shape" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/shape/" --- `shape` 方法用于指定线图层绘制什么样的线。 ### shape('line') 绘制路径图。 `line` 路径是最普通的线图层,支持配置宽度和高度,支持配置纹理和动画。 ```js layer.shape('line'); ``` ### shape('arc') `arc` 弧线通过贝塞尔曲线算法计算出弧线的的路径,支持配置纹理和动画。 ```js layer.shape('arc'); ``` ### shape('arc3d') `arc3d` 3d 弧线是在垂直地图两点之间的弧线,具有高度,支持配置纹理和动画。 ```js layer.shape('arc3d'); ``` ### shape('greatcircle') `greatcircle` 大圆航线是地图两个点最近距离的连线,支持配置纹理和动画。 ```js layer.shape('greatcircle'); ``` ### shape('wall') `wall` 是垂直地图的围墙,支持配置高度,纹理和动画。 ```js layer.shape('wall'); ``` ### shape('simple') `simple` 线图层,宽度始终为 `1px`。 ```js layer.shape('simple'); ``` ### shape('flowline') `flowline` 流向图, 2.17 版本新增 #### 腾讯地图 - Canonical page: https://l7.antv.antgroup.com/zh/api/map/tencent/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/tencent.md - Description: 腾讯地图 --- title: "腾讯地图" description: "腾讯地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/tencent/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 L7 目前支持的腾讯地图是[JavaScript API GL](https://lbs.qq.com/webApi/javascriptGL/glGuide/glOverview),也是腾讯地图官方推荐使用版本。 ### 申请token 使用腾讯地图之前,需要申请腾讯地图密钥,如何申请腾讯地图密钥[点我查看](https://lbs.qq.com/webApi/javascriptGL/glGuide/glBasic)。 ⚠️ L7 内部设置了默认 token,仅供测试使用。 ### import ```javascript import { TencentMap } from '@antv/l7-maps'; ``` ## 初始化地图 ```ts import { Scene, PointLayer } from '@antv/l7'; import { TencentMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new TencentMap({ zoom: 10, minZoom: 5, maxZoom: 18, }), }); ``` 腾讯底图 [示例地址](/zh/examples/map/map/tencentmap/)、腾讯地图实例化[示例地址](/zh/examples/map/map/tmapinstance/) ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### Shape - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/shape/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/shape.md - Description: Shape --- title: "Shape" description: "Shape" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/shape/" --- `shape` 方法用于指定点图层绘制什么样的图形,如绘制三角形或者是正方形,还是文字、图标之类的。 ### shape(fillShape: IFillShape) 点图层的贴地的几何图形,如圆形、正方形、三角形等。 🌟 若是使用简单的圆点图层,建议使用 `simple` 代替 `circle` 以获得更好的性能。 ```js // shape 支持的各种形状 type IFillShape = | 'circle' | 'square' | 'hexagon' | 'triangle' | 'pentagon' | 'octogon' | 'hexagram' | 'rhombus' | 'vesica'; layer.shape('circle'); ``` ### shape(column: IColumn) 点的类型为垂直地图的柱子。 ```js type IColumn = 'cylinder' | 'triangleColumn' | 'hexagonColumn' | 'squareColumn'; layer.shape('cylinder'); layer.shape('triangleColumn'); layer.shape('hexagonColumn'); layer.shape('squareColumn'); ``` ### shape('simple') `simple` 点精灵是特殊的点图层,始终面向相机,且大小受到设备的限制。 ```js layer.shape('simple'); ``` ### shape('dot') `dot` 点精灵是特殊的点图层,始终面向相机,且大小受到设备的限制。 ```js layer.shape('dot'); ``` ### shape(field: string, 'text') 绘制文字,第一个参数为数值中的字段,第二个参数固定为 `text`。 ```js const point = new PointLayer() .source([{ lng: 120, lat: 30, name: 'test' }], { parser: 'json', x: 'lng', y: 'lat', }) .shape('test', 'text'); ``` ### shape(iconName: string) `shape` 的值为 `scene.addImage` 全局添加的图片资源的名称。 ```js 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( [ { longitude: 120, latitude: 30, name: 'name', }, ], { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }, ) .shape('name', ['00', '01', '02']) // shape 支持映射写法 .size(25); scene.addLayer(imageLayer); const imageLayer2 = new PointLayer() .source( [ { longitude: 122, latitude: 30, name: 'name', }, ], { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }, ) .shape('00') // shape 直接传值 .size(25); scene.addLayer(imageLayer2); ``` ### shape('radar') ```js const layer = new PointLayer() .source( [ { lng: 120, lat: 30, }, ], { parser: { type: 'json', x: 'lng', y: 'lat', }, }, ) .size(25) .color('#f00') .shape('radar') .animate(true); ``` 🌟 雷达图需要设置 `animate` 为 `true` #### Shape - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/shape/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/shape.md - Description: Shape --- title: "Shape" description: "Shape" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/shape/" --- `shape` 方法用于指定面图层绘制图形的类型,如填充图,填充线,挤出集合体等。 ### shape('fill') `shape` 为 `fill` 几何图层用于绘制平面的几何图形。 ```js layer.shape('fill'); ``` ### shape('extrude') `shape` 为 `extrude` 几何图层用于绘制 3D 的几何体。 ```js layer.shape('extrude'); ``` ### extrusion extrude 图层的升级版, 支持 extrusionBase(基础高度)数据映射 ```js layer.shape('extrusion'); ``` ### shape('water') `shape` 为 `water` 几何图层用于绘制平面水体。 ```js layer.shape('water'); ``` ### shape('ocean') `shape` 为 `ocean` 几何图层用于绘制平面海洋水体。 ```js layer.shape('ocean'); ``` ### shape('line') `shape` 为 `line` 几何图层用于绘制线。 ```js layer.shape('line'); ``` ### shape('point_fill') `shape` 为 `point_fill` 几何图层用于绘制填充点。 ```js layer.shape('point_fill'); ``` ### shape('point_image') `shape` 为 `point_image` 几何图层用于绘制点图标。 ```js layer.shape('point_image'); ``` ### shape('point_extrude') `shape` 为 `point_extrude` 几何图层用于绘制柱子。 ```js layer.shape('point_extrude'); ``` ### shape('text') `shape` 为 `text` 几何图层用于绘制文字。 ```js layer.shape('text'); ``` #### Raster RGB - Canonical page: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_rgb/ - Markdown source: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_rgb.md - Description: Raster RGB --- title: "Raster RGB" description: "Raster RGB" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/raster_layer/raster_rgb/" --- ## 简介 `Raster RGB ` 波段组合可视化,不同波段映射到 R/G/B 通道可视化 ## source raster-rgb source 是将多波段数据合成 RGB数据进行展示,如对 LandSat8 数据我们可以按照 5,4,3 或者 4,3,2 波段进行RGB组合显示 - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `rgb` ```ts layer.source(bandsValues, { parser: { type: 'rgb', width: bandsValues.width, height: bandsValues.height, bands: [4, 3, 2], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number,number] 指定 R/G/B 通道对应的数据索引,data 数组长度需要大于等于 3 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4,3 波段这样要设置为 4,3, 2) - width 长度 `必选` - height 宽度 `必选` - countCut 颜色拉伸参数 `[number,number]` 数值为百分比,默认值 `[2,98]` `可选` ### 完整示例 [Raster RGB](../../../../examples/raster/rgb/#543) ## style ### opacity 透明度 ```js layer.style({ opacity: 0.5, }); ``` #### CSV - Canonical page: https://l7.antv.antgroup.com/zh/api/source/csv/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/csv.md - Description: CSV --- title: "CSV" description: "CSV" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/csv/" --- L7 支持 CSV 以逗号分隔的 CSV 数据加载。 CSV 是文本数据结构,很难表达复杂的地理数据结构,因此 CSV 仅支持两种数据结构 - 点数据:需要指定经度、纬度坐标 - 线段、弧线数据:需要指定 **起止点** 的经度、纬度坐标 ## parser - type string 必选 json - x string 点数据表示 经度 - y string 点数据表示 纬度 - x1 string 经度 - x2 string 纬度 ### 点数据通过 CSV 加载 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, }); ``` [CSV 数据 demo 示例](/zh/examples/point/bubble/scatter/) ### 线段弧线数据通过 CSV 加载 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng1', y1: 'lat2', }, }); ``` [CSV 线段数据 demo 示例](/zh/examples/gallery/basic/arc-circle/) #### Scale 缩放尺 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/scale.md - Description: Scale 缩放尺 --- title: "Scale 缩放尺" description: "Scale 缩放尺" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/scale/" --- 该控件用于显示地图上的距离与地面上相应距离的比率。 ## 使用 [示例](/zh/examples/component/control/scale/) ```ts import { Scene, Scale } from '@antv/l7'; const scene = new Scene({ //... }); scene.on('loaded', () => { const scale = new Scale({ zoomInTitle: '放大', zoomOutTitle: '缩小', }); scene.addControl(scale); }); ``` ## 配置 | 名称 | 说明 | 类型 | 默认值 | | -------------- | ------------------------------------ | --------- | ------- | | lockWidth | 是否固定容器宽度 | `boolean` | `true` | | maxWidth | 组件的容器最大宽度 | `number` | `100` | | metric | 展示**千米**格式的比例尺 | `boolean` | `true` | | imperial | 展示**英里**格式的比例尺 | `boolean` | `false` | | updateWhenIdle | 是否只在拖拽和缩放结束后才更新比例尺 | `boolean` | `false` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/style/" --- `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 🌟 蜂窝热力图和网格热力图的 `style` 样式可以参考实际绘制的图层。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | ### heatmap `shape` 为 `heatmap`、`heatmap3D` 类型的时候,绘制经典热力图。 | style | 类型 | 描述 | 默认值 | | ---------- | -------- | ------------ | ------ | | intensity | `number` | 热力的强度 | `10` | | radius | `number` | 热力点的半径 | `10` | | rampColors | `number` | 热力的色值 | `1` | #### rampColors - colors 颜色数组 - positions 数据区间 配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。 ⚠️ colors, positions 的长度要相同 ```javascript layer.style({ rampColors: { colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'], positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], }, }); ``` ### hexagon 绘制蜂窝热力图。 | style | 类型 | 描述 | 默认值 | | -------- | -------- | ------------ | ------ | | angle | `number` | 图形旋转角度 | `0` | | coverage | `number` | 图形覆盖比率 | `0.9` | ### grid 绘制网格热力图。 | style | 类型 | 描述 | 默认值 | | -------- | -------- | ------------ | ------ | | coverage | `number` | 图形覆盖比率 | `1` | #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/image_layer/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/image_layer/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/image_layer/style/" --- `imagelayer` 的 `style` 参数只支持 `opacity`。 | style | 类型 | 描述 | 默认值 | | ---------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | | brightness | `number` | 图形的亮度 | `1` | | contrast | `number` | 图形的对比度 | `1` | | saturation | `number` | 图形的饱和度 | `1` | | gamma | `number` | 图形的伽马值 | `1` | #### MapBox 地图 - Canonical page: https://l7.antv.antgroup.com/zh/api/map/mapbox/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/mapbox.md - Description: MapBox 地图 --- title: "MapBox 地图" description: "MapBox 地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/mapbox/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - [Mapbox-gl 官网](https://docs.mapbox.com/mapbox-gl-js/) - [ Mapbox-gl GitHub](https://github.com/mapbox/mapbox-gl-js) ## 申请token [申请token](https://docs.mapbox.com/help/getting-started/access-tokens/) ## 初始化地图 ```ts import { Scene, PointLayer } from '@antv/l7'; import { Mapbox } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Mapbox({ zoom: 10, minZoom: 0, maxZoom: 18, token: 'xxxx', //必须 }), }); ``` #### 传入 Mapbox 地图实例 ```javascript mapboxgl.accessToken = 'xxxx - token'; const map = new mapboxgl.Map({ container: 'map', // container id style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location center: [-74.5, 40], // starting position [lng, lat] zoom: 9, // starting zoom }); const scene = new Scene({ id: 'map', map: new Mapbox({ mapInstance: map, }), }); ``` ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/style/" --- `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | #### 样式数据映射 默认样式配置为常量值,某些配置也支持数据映射,映射定义同 color、size参数一致。 - field: 映射字段 - value: 映射区间或者自定义回调函数 如: ```ts layer.style({ opacity:{ field:'name' value:[0.1,0.5,1], } }) ``` ### 2D shape `shape` 为平面图形、如三角形、正方等。 - [IFillShape](/zh/api/point_layer/shape#shapefillshape-ifillshape) | style | 类型 | 是否支持数据映射 | 描述 | 默认值 | | ------------- | -------------------------------------------------- | ---------------- | -------------------------------------------- | -------- | | stroke | `string` | 是 | 图形边框颜色 | `#fff` | | strokeWidth | `number` | 否 | 图形边框宽度 | `0` | | strokeOpacity | `number` | 否 | 图形边框透明度 | `1` | | blur | `number` | 否 | 图形模糊半径 | `0` | | offsets | `[number, number]` | 是 | 点偏移 | `[0, 0]` | | rotation | `number` | 是 | 旋转角度 | `0` | | anchor | [anchorType](/zh/api/point_layer/style#anchortype) | 是 | 图形锚点位置,控制图形相对于坐标点的对齐方式 | `center` | | raisingHeight | `number` | 否 | 抬升高度 | `0` | | heightfixed | `boolean` | 否 | 点大小单位 | `pixel` | #### unit - pixel 默认值 - meter 单位为米 ```js type IUnit = 'pixel' | 'meter'; ``` 点图层支持等面积点,点大小的单位是米,同样通过 size 方法设置大小 ```javascript import { PointLayer } from '@antv/l7'; const layer = PointLayer().source(data).shape('circle').size(100).color('#f00').style({ unit: 'meter', }); ``` 🌟 从 v2.7.9 版本开始支持高德地图、高德地图 2.0、Mapbox 地图 ### 3D column `shape` 为 3D 柱图。 - [IColumn](/zh/api/point_layer/shape#shapecolumn-icolumn) | style | 类型 | 描述 | 默认值 | | ----------- | --------- | -------------------- | ------- | | depth | `boolean` | 图形是否开启深度检测 | `true` | | pickLight | `boolean` | 拾取高亮是否计算光照 | `false` | | lightEnable | `boolean` | 颜色是否参与光照计算 | `true` | | heightfixed | `boolean` | 是否是固定高度 | `false` | ### 3D column linear 柱图支持配置渐变色,在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 | style | 类型 | 描述 | 默认值 | | ------------- | --------------- | ---------------- | ------ | | sourceColor | `color` | 柱子底部颜色 | `/` | | targetColor | `color` | 柱子顶部颜色 | `/` | | opacityLinear | `IOpcityLinear` | 柱子的透明度渐变 | `/` | #### color ```js const color = `rgb(200, 100, 50)`; const color2 = '#ff0'; ``` #### opacityLinear ```js type IDir = 'up' | 'down'; interface IOpcityLinear = { enable: boolean; dir: IDir; } ``` ### text `shape` 为文字。 - [text](/zh/api/point_layer/shape#shapefield-string-text) | style | 类型 | 描述 | 是否支持数据映射 | 默认值 | | ---------------- | -------------------------------------------------- | -------------------------- | ---------------- | ------------ | | opacity | `number` | 透明度 | 是 | `#fff` | | stroke | `string` | 图形边框颜色 | 是 | `#fff` | | strokeWidth | `number` | 图形边框颜色 | 否 | `0` | | textOffset | `[number, number]` | 文字的偏移 | 是 | `[0, 0]` | | textAnchor | [anchorType](/zh/api/point_layer/style#anchortype) | 文字对齐锚点 `text` | 是 | `center` | | spacing | `number` | 文字间隔 | 否 | `2` | | rotation | `number` | 旋转角度 | 是 | `0` | | padding | `number` | 文字内边框宽度 | 否 | `2` | | halo | `number` | 文字边缘光晕宽度 | 否 | `0.5` | | gamma | `number` | 文字的颜色参数 | 否 | `2` | | fontWeight | `string` | 文字的大小 | 否 | `400` | | fontFamily | [font](/zh/api/point_layer/style#font) | 字体 | 否 | `sans-serif` | | textAllowOverlap | `boolean` | 文字是否允许覆盖 | 否 | `false` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | #### anchorType 图形/文字对齐锚点,用于控制图形或文字相对于坐标点的对齐方式。 - 在 2D shape(如 `circle`、`square` 等)中通过 `anchor` 属性使用,控制图形相对于坐标点的位置 - 在 text shape 中通过 `textAnchor` 属性使用,控制文字相对于坐标点的位置 ```javascript export enum anchorType { 'CENTER' = 'center', 'TOP' = 'top', 'TOP-LEFT' = 'top-left', 'TOP-RIGHT' = 'top-right', 'BOTTOM' = 'bottom', 'BOTTOM-CENTER' = 'bottom-center', 'BOTTOM-LEFT' = 'bottom-left', 'BOTTOM-RIGHT' = 'bottom-right', 'LEFT' = 'left', 'RIGHT' = 'right', } ``` **anchor 使用示例(2D shape)** ```javascript // 气泡底部对齐到坐标位置,常用于地图标注场景 const bubbleLayer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' }, }) .shape('circle') .size(30) .color('#5B8FF9') .style({ anchor: 'bottom', }); // anchor 支持数据映射 const layer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' }, }) .shape('circle') .size(20) .color('#5B8FF9') .style({ anchor: { field: 'type', value: ['center', 'bottom', 'top'], }, }); ``` #### font css fontFamily。 ```js const font = 'sans-serif'; const font2 = 'Times New Roman'; ``` ### simple `shape` 为简单点图形(精灵)。 - [simple](/zh/api/point_layer/shape#shapesimple) | style | 类型 | 描述 | 默认值 | | ------------- | ------------------ | ------------ | -------- | | stroke | `string` | 图形边框颜色 | `#fff` | | strokeWidth | `number` | 图形边框颜色 | `0` | | strokeOpacity | `number` | 图形边框宽度 | `1` | | offsets | `[number, number]` | 点偏移 | `[0, 0]` | ### icon `shape` 为图标类型。 - [icon](/zh/api/point_layer/shape#shapeiconname-string) | style | 类型 | 描述 | 数据映射 | 默认值 | | ------------- | ------------------ | -------------------------------------------------------------------------- | -------- | -------- | | offsets | `[number, number]` | 点偏移 | 否 | `[0, 0]` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | | rotation | `number` | 旋转角度 | 是 | `0` | | allowOverlap | `boolean` | 图标是否允许压盖,`false` 时开启碰撞避让自动隐藏重叠图标 | 否 | `true` | | padding | `[number, number]` | 碰撞检测包围盒的额外边距 `[水平, 垂直]`,仅在 `allowOverlap: false` 时生效 | 否 | `[0, 0]` | #### rotation 图标的旋转角度。 ```js const imageLayer = new PointLayer({ layerType: 'fillImage' }) .source(data) .shape('wind', (wind) => { if (wind === 'up') { return 'arrBlue'; } return 'arrRed'; }) .size(15) .style({ rotation: 0, }); ``` #### allowOverlap 控制图标在屏幕上是否允许相互压盖。设置为 `false` 时,L7 会在每次地图缩放或平移后对所有图标执行碰撞检测,自动隐藏与已放置图标重叠的图标,效果与 `textAllowOverlap` 一致。 ```js const imageLayer = new PointLayer() .source(data, { parser: { type: 'json', x: 'lng', y: 'lat' } }) .shape('icon') .size(15) .style({ allowOverlap: false, // 开启碰撞避让 padding: [4, 4], // 图标之间保留 4px 间距 }); ``` ### radar `shape` 为雷达图。 - [radar](/zh/api/point_layer/shape#shaperadar) | style | 类型 | 描述 | 默认值 | | ----- | -------- | ---------------- | ------ | | speed | `number` | 雷达图旋转的速度 | `1` | #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/style/" --- `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 默认值 | | ------- | -------- | ------------ | ------ | | opacity | `number` | 图形的透明度 | `1` | ### fill `shape` 为平面填充几何体。 - [fill](/zh/api/polygon_layer/shape#shapefill) | style | 类型 | 描述 | 默认值 | | ------------- | ---------------- | -------- | ------ | | raisingHeight | `number` | 抬升高度 | `0` | | opacityLinear | `IOpacityLinear` | 透明渐变 | `/` | #### opacityLinear ```js type IDir = 'in' | 'out'; interface IOpacityLinear { enable: false; dir: IDir; } ``` ### extrude `shape` 为挤出几何体。 - [extrude](/zh/api/polygon_layer/shape#shapeextrude) | style | 类型 | 描述 | 默认值 | | ------------- | --------- | -------------------------- | ------- | | raisingHeight | `number` | 抬升高度 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | `false` | | topsurface | `boolean` | 顶部是否显示 | `true` | | sidesurface | `boolean` | 侧面是否显示 | `true` | | sourceColor | `IColor` | 侧面底部颜色 | `/` | | targetColor | `IColor` | 侧面顶部颜色 | `/` | ### extrusion `shape` 为挤出几何体。 - [extrusion](/zh/api/polygon_layer/shape#extrusion) | style | 类型 | 描述 | 是否支持数据映射 | 默认值 | | ------------- | -------- | ---------------- | ---------------- | ------ | | extrusionBase | `number` | 基础高度,单位米 | 支持 | `0` | #### linear 几何体图层支持配置渐变效果(sourceColor、targetColor),在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 ### water `shape` 为水体表面几何体。 - [water](/zh/api/polygon_layer/shape#shapewater) | style | 类型 | 描述 | 默认值 | | ------------ | -------- | -------- | ------ | | speed | `number` | 水波速度 | `0.5` | | waterTexture | `string` | 水面贴图 | `0` | `waterTexture` 默认值为 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*EojwT4VzSiYAAAAAAAAAAAAAARQnAQ' ### ocean `shape` 为海洋表面几何体。 - [ocean](/zh/api/polygon_layer/shape#shapeocean) | style | 类型 | 描述 | 默认值 | | ----------- | -------- | -------- | --------- | | watercolor | `IColor` | 水面颜色 | `#6D99A8` | | watercolor2 | `IColor` | 水面颜色 | `#0F121C` | ### other 几何体图层支持的其他 `shape` 都有对应的图层,可以参考对应图层的样式参数。 #### Raster NDI - Canonical page: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_ndi/ - Markdown source: https://l7.antv.antgroup.com/zh/api/raster_layer/raster_ndi.md - Description: Raster NDI --- title: "Raster NDI" description: "Raster NDI" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/raster_layer/raster_ndi/" --- ## 简介 `Raster NDI` Normalized Difference Indices 归一化指数计算,提供另个波段,进行归一化计算 ## source raster-ndi(Normalized Difference Indices) source 是将多波段数据进行归一化指数计算,比如计算NDVI/NDWI 等指数, - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `ndi` ```ts layer.source(bandsValues, { parser: { type: 'ndi', width: bandsValues.width, height: bandsValues.height, bands: [4, 3], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number] 指定需要归一化的波段,data 数组长度需要大于等于 2 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4, 波段这样要设置为 4,3) - width 长度 `必选` - height 宽度 `必选` ### 完整示例 [Raster ndi](../../../../examples/raster/ndi/#ndbi) ## style `style` 方法用于配制图层的样式, - 单通道 绘制结果由是单一的数值控制,如灰度图,数值对应的颜色可以通过表示配置 `rampColors` 色带控制。 ```js layer.style({ opacity: 0.5, }); ``` ### 配置 | style | 类型 | 描述 | 默认值 | | ----------- | ------------------ | ------------------------------------------- | ------------- | | opacity | `number` | 图形的透明度 | `1` | | clampLow | `boolean` | 设置为 `true`,低于 `domain` 的数据将不显示 | `false` | | clampHigh | `boolean` | 设置为 `true`,高于 `domain` 的数据将不显示 | `false` | | domain | `[number, number]` | 数据映射区间 | `[ 0, 8000 ]` | | noDataValue | `number` | 不会显示的值 | `-9999999` | | rampColors | `IRampColors` | 值域映射颜色的色带 | `/` | ### rampColors 颜色色带 - type 类型 支持 `linear','quantize','custom','cat' - colors 颜色数组 - positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值 ⚠️ 2.13 新增特性 #### cat 枚举类型色带 枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举 ```tsx { type:'cat', colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'], positions:[1,20,101,102,200], } ``` #### quantize 等间距分类色带 等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。 等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数 ```tsx rampColors: { type:'quantize', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'] } ``` #### linear 线性连续色带 linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1 ```tsx rampColors: { type:'linear', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions [0,200,1000,4000,8000] } ⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。 ``` #### custom 自定义分段色带 自定义分段色带区别等间距色带,用户自定义分段间隔。 自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions ```tsx rampColors: { type:'custom', colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'], positions: [0,200,1000,4000,8000,10000] } ``` #### React 组件库 - Canonical page: https://l7.antv.antgroup.com/zh/api/react/react/ - Markdown source: https://l7.antv.antgroup.com/zh/api/react/react.md - Description: React 组件库 --- title: "React 组件库" description: "React 组件库" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/react/react/" --- ### LarkMap LarkMap 为 L7 react 地图组件库提供地图容器组件,相关地图组件与 Hooks 需放到容器组件内部才能使用,容器组件可通过属性配置不同的地图,支持 Mapbox、Gaode、Baidu、Tencent 及 L7Map 作为底图,其中 Baidu 和 Tencent 仍为实验特性。 ```tsx import type { LarkMapProps } from '@antv/larkmap'; import { LarkMap } from '@antv/larkmap'; import React from 'react'; const config: LarkMapProps = { mapType: 'Gaode', mapOptions: { style: 'light', center: [120.210792, 30.246026], zoom: 9, // token: '你申请的 Key', }, }; export default () => ( LarkMap ); ``` [L7 React 组件库](https://larkmap.antv.antgroup.com/components/lark-map) #### Image - Canonical page: https://l7.antv.antgroup.com/zh/api/source/image/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/image.md - Description: Image --- title: "Image" description: "Image" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/image/" --- Image 数据主要用于在地图上根据经纬度范围添加图片,比如一幅纸制地图扫描版需要显示在地图上。 ## parser - type: image - extent: 图像的经纬度范围 `[minlng, minlat,maxLng, maxLat]` 可选 - coordinates: `[[number,number],[number,number],[number,number],[number,number]]`; 可选 四个地理坐标,表示为经度和纬度数字的数组,定义图像的角点。 坐标从图像的左上角开始并按顺时针顺序进行。 它们不必代表矩形。 ```javascript layer.source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', { parser: { type: 'image', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` 倾斜图片 ```ts layer.source( 'https://mdn.alipayobjects.com/huamei_gjo0cl/afts/img/A*vm_9S64uA0UAAAAAAAAAAAAADjDHAQ/original', { parser: { type: 'image', coordinates: [ [100.959388, 41.619522], [101.229887, 41.572654], [101.16971, 41.377836], [100.900015, 41.424628], ], }, }, ); ``` #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/common/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/common/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/common/style/" --- 瓦片图层的 `style` 参数和使用的图层相关。如矢量点图层,`style` 的参数就是对应点图层的参数。 ### raster tile #### domain: [number, number] 设置数据映射的定义域。 ps:固定值域为 `[0, 1]`,我们将传入的值(domain) 映射到值域 `[0, 1]` 后从 `rampColor` 构建的色带上取颜色,rgb 多通道栅格不支持。 #### clampLow/clampHigh: boolean `clampLow` 的默认值为 `false`,设置为 `true`,低于 `domain` 的数据将不显示。 `clampHigh` 的默认值为 `false`,设置为 `true`,高于 `domain` 的数据将不显示。 ps:rgb 多通道栅格不支持 #### rampColors - colors 颜色数组 - positions 数据区间 配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。 ⚠️ colors, positions 的长度要相同 ```javascript layer.style({ rampColors: { colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'], positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], }, }); ``` ps:⚠️ color, position 的长度要相同,rgb 多通道栅格不支持 ### vector tile 矢量图层的 `style` 样式和普通图层保持一致。 ### event 🌟 数据栅格支持图层事件,目前图片栅格暂时不支持图层事件。 ##### 绑定事件 🌟 数据栅格瓦片 ```javascript // 绑定事件的方式和普通图层保持一致 layer.on('click', e => {...}) ``` #### 事件参数 🌟 数据栅格瓦片 数据栅格瓦片的事件参数相比于普通图层的事件返回了新的参数。 #### value: number 🌟 数据栅格瓦片 鼠标事件位置的瓦片的实际数值。 #### 瓦片调试图层 - Canonical page: https://l7.antv.antgroup.com/zh/api/tile/tile_debug_layer/ - Markdown source: https://l7.antv.antgroup.com/zh/api/tile/tile_debug_layer.md - Description: 瓦片调试图层 --- title: "瓦片调试图层" description: "瓦片调试图层" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/tile/tile_debug_layer/" --- 显示瓦片范围和行列号信息,用于测试验证瓦片服务 ``` import { Scene, TileDebugLayer } from '@antv/l7'; const debugerLayer = new TileDebugLayer(); scene.addLayer(debugerLayer); ``` #### Fullscreen 全屏 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/fullscreen/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/fullscreen.md - Description: Fullscreen 全屏 --- title: "Fullscreen 全屏" description: "Fullscreen 全屏" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/fullscreen/" --- 用于控制地图区域的**全屏**和**退出全屏**的控制按钮控件。 ## 使用 [示例](/zh/examples/component/control/fullscreen/) ```ts import { Scene, Fullscreen } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const fullscreen = new Fullscreen({ btnText: '全屏', exitBtnText: '退出全屏', }); scene.addControl(fullscreen); }); ``` ## 配置 | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------- | ----------------------------- | | btnIcon | 按钮图标 | `HTMLElement` \| `SVGElement` | | btnText | 按钮内容文本 | `string` | | title | 按钮的 `title` 属性 | `string` | | vertical | 在 btnIcon 有值的情况下,按钮内的图标和文案是否纵向排列 | `boolean` | | 名称 | 说明 | 类型 | | ----------- | --------------------------------- | ----------------------------- | | exitBtnIcon | 退出全屏按钮的图标 | `HTMLElement` \| `SVGElement` | | exitBtnText | 退出全屏按钮的文本 | `string` | | exitTitle | 退出全屏按钮的文本的 `title` 属性 | `string` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ---------------- | ------------------------------- | ------------ | | toggleFullscreen | 进入/退出全屏地图部分的全屏状态 | `() => void` | | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ---------------- | ------------------------ | --------------------------------- | | fullscreenChange | 当全屏状态发生变化时触发 | `(isFullscreen: boolean) => void` | | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### Size - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/size/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/size.md - Description: Size --- title: "Size" description: "Size" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/size/" --- 线图层的 `size` 方法可以设置线的宽度和高度。 ### ILineSize: number | [number, number] - size 类型为 number 则表示 line 的宽度 - size 类型为 [number , number] 分别表示宽度和高度 ```javascript lineLayer.size(1); // 线的宽度为 1 lineLayer.size([1, 2]); // 宽度为1,高度2 ``` ### size(width: ILineSize) 线图层可以直接设置宽度值。图层中所有的线使用一个宽度。 ```js layer.size(2); ``` ### size(field: string) 线图层的宽度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source({ type: 'Feature', properties: { lineSize: 2, }, geometry: { type: 'LineString', coordinates: [ [119.988511, 30.269614], [119.9851, 30.269323], [119.99271, 30.22088], ], }, }); layer.size('lineSize'); ``` ### size(field: string, domain: ILineSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => ILineSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为线图层实际的宽高。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` #### MapLibre - Canonical page: https://l7.antv.antgroup.com/zh/api/map/maplibre/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/maplibre.md - Description: MapLibre --- title: "MapLibre" description: "MapLibre" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/maplibre/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - [MapLibre](https://maplibre.org/) - [ MapLibre GitHub](https://github.com/maplibre/maplibre-gl-js) ## 初始化地图 ```ts import { Scene, PointLayer } from '@antv/l7'; import { MapLibre } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new MapLibre({ zoom: 10, style: 'https://api.maptiler.com/maps/streets/style.json?key=YbCPLULzWdf1NplssEIc', // style URL minZoom: 0, maxZoom: 18, }), }); ``` #### 传入 MapLibre 地图实例 ```javascript import { Scene, PointLayer } from '@antv/l7'; import { MapLibre } from '@antv/l7-maps'; var map = new maplibregl.Map({ container: 'map', // container id style: 'https://demotiles.maplibre.org/style.json', // style URL center: [0, 0], // starting position [lng, lat] zoom: 1, // starting zoom }); const scene = new Scene({ id: 'map', map: new MapLibre({ mapInstance: map, }), }); ``` ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### Size - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/size/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/size.md - Description: Size --- title: "Size" description: "Size" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/size/" --- `size` 方法用于设置点图层图形的大小。 ### IPointSize: number |[number, number] | [number, number, number] - size 类型为 number 则表示 point 的半径 - size 类型可以为 [number, number]|[number, number, number] 表示柱子的半径和高度 ```javascript pointLayer.size(1); pointLayer.size([2, 10]); // 柱子半径为 2x2.高为 10 pointLayer.size([2, 4, 10]); // 柱子半径为 2x4,高为 10 ``` ### size(width: IPointSize) 点图层可以直接设置半径。图层中所有的点使用一个宽度。 ```js layer.size(2); ``` ### size(field: string) 点图层的宽度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, r: 2, }, ]); layer.size('r'); ``` ### size(field: string, domain: IPointSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => IPointSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为点图层实际的半径。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` #### Size - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/size/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/size.md - Description: Size --- title: "Size" description: "Size" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/size/" --- `size` 方法用于设置 Polygon 的高度 ### IPointSize: number |[number, number] | [number, number, number] - size 类型为 number 则表示 Polygon 的高度 ```javascript pointLayer.size(1); ``` ### size(width: IPointSize) 面图层可以直接设置半径。图层中所有的点使用一个高度。 ```js layer.size(2); ``` ### size(field: string) 面图层的高度可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, r: 2, }, ]); layer.size('r'); ``` ### size(field: string, domain: IPointSize[]) `size` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.size('type', [1, 2, 3]); ``` ### size(field: string, callback: () => IPointSize ) `size` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为面图层实际高度。 ```js layer.size('type', (value) => { switch (value) { case 'path': return 1; case 'road': return 2; } }); ``` #### Raster Data - Canonical page: https://l7.antv.antgroup.com/zh/api/source/raster/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/raster.md - Description: Raster Data --- title: "Raster Data" description: "Raster Data" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/raster/" --- Raster data 数据栅格的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图、植被分布图和夜光图。 - data 数据 - option 配置项 - parser 数据解析参数 ### data data 解析后的数据,为数组 ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` 以 geotiff 为例需要先将数据解析出来,作为 data 输入给 source ```tsx import * as GeoTIFF from 'geotiff'; async function getTiffData() { async function getTiffData() { const response = await fetch( 'https://gw.alipayobjects.com/zos/antvdemo/assets/light_clip/lightF182013.tiff', ); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { data: values[0], width, height, }; } } const tiffdata = await getTiffData(); layer.source(tiffdata.data, { parser: { type: 'raster', width: tiffdata.width, height: tiffdata.height, extent: [73.4821902409999979, 3.8150178409999995, 135.1066187319999869, 57.6300459959999998], }, }); ``` ### parser - type: raster - extent: 栅格的经纬度范围 [minlng, minlat,maxLng, maxLat] - width 数据宽度 - height 数据高度 根据栅格数据的经纬度范围,将其添加到地图上。 ```javascript layer.source(rasterData, { parser: { type: 'raster', extent: [121.168, 30.2828, 121.384, 30.4219], }, }); ``` ### 完整示例 [Raster ndi](../../../../examples/raster/data/#dem) #### Raster NDI - Canonical page: https://l7.antv.antgroup.com/zh/api/source/raster_ndi/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/raster_ndi.md - Description: Raster NDI --- title: "Raster NDI" description: "Raster NDI" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/raster_ndi/" --- raster-ndi(Normalized Difference Indices) source 是将多波段数据进行归一化指数计算,比如计算NDVI/NDWI 等指数, - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `ndi` ```ts layer.source(bandsValues, { parser: { type: 'ndi', width: bandsValues.width, height: bandsValues.height, bands: [4, 3], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number] 指定需要归一化的波段,data 数组长度需要大于等于 2 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4, 波段这样要设置为 4,3) - width 长度 `必选` - height 宽度 `必选` ### 完整示例 [Raster ndi](../../../../examples/raster/ndi/#ndbi) #### Raster RGB - Canonical page: https://l7.antv.antgroup.com/zh/api/source/raster_rgb/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/raster_rgb.md - Description: Raster RGB --- title: "Raster RGB" description: "Raster RGB" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/raster_rgb/" --- raster-rgb source 是将多波段数据合成 RGB数据进行展示,如对 LandSat8 数据我们可以按照 5,4,3 或者 4,3,2 波段进行RGB组合显示 - data 数据 - option 配置项 - parser 数据解析参数 - type 解析类型 `rgb` ```ts layer.source(bandsValues, { parser: { type: 'rgb', width: bandsValues.width, height: bandsValues.height, bands: [4, 3, 2], // 从零开始 extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }); ``` ### data ```ts type RasterDataType = | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array; ``` data 为数组类型 `RasterDataType[]` - 如果是多波段 Tiff 可以直接使用geotiff,js 读取所有波段, - 如果是单文件单波段数据,需要单独读取并合并成一个数据。 单文件多波段读取示例 ```ts async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image1 = await tiff.getImage(); const bandsValues = await image1.readRasters(); return bandsValues; } ``` ### parser - type 解析类型 'rgb' `必选` - bands `[number,number,number] 指定 R/G/B 通道对应的数据索引,data 数组长度需要大于等于 3 `必选` 注:bands 序号从零开始(landsat 8 里的 5,4,3 波段这样要设置为 4,3, 2) - width 长度 `必选` - height 宽度 `必选` - countCut 颜色拉伸参数 `[number,number]` 数值为百分比,默认值 `[2,98]` `可选` ### 完整示例 [Raster RGB](../../../../examples/raster/rgb/#543) #### GeoLocate 定位 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/geolocate/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/geolocate.md - Description: GeoLocate 定位 --- title: "GeoLocate 定位" description: "GeoLocate 定位" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/geolocate/" --- 使用浏览器环境的 `nagigator` 的 `getlocation` 方法,使用浏览器打开位置感应能力获取当前用户所在经纬度。 ## 说明 [示例](/zh/examples/component/control/geolocate/) **注意:** - 在使用该能力时,会需要用户对浏览器打开位置感知能力进行鉴权。 - 当前浏览器获取到的坐标是 `WGS84` 地理坐标系,在高德地图上使用会有偏差,可以使用 `transform` 配置进行坐标系的转换。 ## 使用 ```ts import { Scene, GeoLocate } from '@antv/l7'; import gcoord from 'gcoord'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const geoLocate = new GeoLocate({ transform: (position) => { // 将获取到基于 WGS84 地理坐标系 的坐标转成 GCJ02 坐标系 return gcoord.transform(position, gcoord.WGS84, gcoord.GCJ02); }, }); scene.addControl(geoLocate); }); ``` ## 配置 | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------- | -------------------------------------------------- | | transform | 格式化通过 `getlocation` 获取到的经纬度的函数,可以用于地理坐标系的转换 | `(position: [number, number]) => [number, number]` | | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------- | ----------------------------- | | btnIcon | 按钮图标 | `HTMLElement` \| `SVGElement` | | btnText | 按钮内容文本 | `string` | | title | 按钮的 `title` 属性 | `string` | | vertical | 在 btnIcon 有值的情况下,按钮内的图标和文案是否纵向排列 | `boolean` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | -------------- | ---------------------- | --------------------------------- | | getGeoLocation | 获取当前用户所在经纬度 | `() => Promise<[number, number]>` | | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### Scale - Canonical page: https://l7.antv.antgroup.com/zh/api/heatmap_layer/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/api/heatmap_layer/scale.md - Description: Scale --- title: "Scale" description: "Scale" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/heatmap_layer/scale/" --- `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` #### Color - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/color/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/color.md - Description: Color --- title: "Color" description: "Color" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/color/" --- `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` #### Scale - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/scale.md - Description: Scale --- title: "Scale" description: "Scale" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/scale/" --- `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` #### Texture - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/texture/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/texture.md - Description: Texture --- title: "Texture" description: "Texture" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/texture/" --- 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) #### Leaflet - Canonical page: https://l7.antv.antgroup.com/zh/api/map/leaflet/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/leaflet.md - Description: Leaflet --- title: "Leaflet" description: "Leaflet" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/leaflet/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - [Leaflet 官网](https://leafletjs.com/) - [Leaflet GitHub](https://github.com/antvis/l7-extensions/tree/master/packages/leaflet) ### 安装 L7-Leaflet 为三方插件 L7本身没有内置,需要独立按照 - [L7-Leaflet GitHub](https://github.com/antvis/l7-extensions/tree/master/packages/leaflet) - [L7-Leaflet Demo ](https://l7-leaflet.antv.vision/) ```ts npm install '@antv/l7-leaflet' ``` or ```js ``` ### 初始化 ```ts import { Scene } from '@antv/l7'; import * as L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { Map } from '@antv/l7-leaflet'; const scene = new Scene({ id: 'map', map: new Map({ pitch: 0, center: [112, 37.8], zoom: 3, minZoom: 1, }), }); ``` ### Leaflet 中使用 L7 ```ts import * as L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { LineLayer } from '@antv/l7'; import { L7Layer } from '@antv/l7-leaflet'; const map = L.map('map', { minZoom: 1, }).setView([30, 112], 3); const mapType = 'vec'; L.tileLayer( 'https://t{s}.tianditu.gov.cn/' + mapType + '_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + mapType + '&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=b72aa81ac2b3cae941d1eb213499e15e', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], attribution: '© 天地图 GS(2022)3124号 - 甲测资字1100471', }, ).addTo(map); const l7layer = new L7Layer().addTo(map); const scene = l7layer.getScene(); ``` #### 城市建筑 - Canonical page: https://l7.antv.antgroup.com/zh/api/other/city_building/ - Markdown source: https://l7.antv.antgroup.com/zh/api/other/city_building.md - Description: 城市建筑 --- title: "城市建筑" description: "城市建筑" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/other/city_building/" --- ## 简介 `CityBuildingLayer` 用于构建城市建筑 3D 模型, 展示城市建筑 ## 使用 ```javascript import { CityBuildingLayer } from '@antv/l7'; ``` ### animate 是否开启动画效果, 仅支持`boolean` 或`enable: boolean` 配置项 ```javascript layer.animate(true); layer.animatte({ enable: true, }); ``` ✨ 在开启 animate 后默认会打开点亮窗户的动画 🌟 开启 animate 动画是打开扫光动画的前提 ### style - baseColor 楼房颜色, - windowColor: 窗户颜色, - brightColor: 点亮窗户颜色 - sweep: 圆形扫光扩散动画相关配置项 - enable: 是否开启扫光扩散 - sweepRadius: 扩散半径 - sweepCenter: 扩散中心店坐标 - sweepColor: 扩散颜色 - sweepSpeed: 扩散速度 - baseColor: 开启 sweep 时的基础颜色 其他 style 配置项同 [baselayer#style](/zh/api/base_layer/base#style) ## 自定义动画频率 自定义动画频率需要 关闭默认动画,通过 `setLight` 方法不断更新时间 ### setLight(time) 参数 time : 时间 毫秒 ```js import { CityBuildingLayer, Scene } from '@antv/l7'; import { Mapbox } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'dark', center: [121.507674, 31.223043], pitch: 65.59312320916906, zoom: 15.4, minZoom: 15, maxZoom: 18, }), }); const buildingLayer = new CityBuildingLayer(); buildingLayer.animate(false); let i = 0; function step() { buildingLayer.setLight(i++); scene.render(); requestAnimationFrame(step); } scene.on('loaded', () => { step(); }); ``` #### demo ```javascript import { Scene, CityBuildingLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', center: [120.173104, 30.244072], pitch: 70.41138037735848, zoom: 17.18, rotation: 2.24, // 358.7459759480504 minZoom: 14, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/ggFwDClGjjvpSMBIrcEx.json') .then((res) => res.json()) .then((data) => { const layer = new CityBuildingLayer({ zIndex: 0, }); layer.source(data); scene.addLayer(layer); }); }); ``` [在线案例](/zh/examples/gallery/animate/build-sweep/) #### Color - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/color/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/color.md - Description: Color --- title: "Color" description: "Color" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/color/" --- `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` #### Scale - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/scale.md - Description: Scale --- title: "Scale" description: "Scale" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/scale/" --- `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` #### Color - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/color/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/color.md - Description: Color --- title: "Color" description: "Color" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/color/" --- `color` 方法用于设置图形的颜色。 ### IColor: string `color` 类型的字符串。 - color 类型可以为 rgb 的写法 `rgb(200, 100, 100)`、`rgba(255, 0, 0, 1)` - color 类型可以为十六进制的写法 `#ffffff`、`#000` - color 类型可以是颜色名称的写法 `red`、`yellow` ### color(color: IColor) 图层可以直接设置颜色值。 ```js layer.color('#f00'); ``` ### color(field: string) 图层的颜色可以根据图层接受的数据值进行映射,接受传入数据的字段作为参数。 ```js layer.source([ { lng: 120, lat: 30, c: '#f00', }, ]); layer.color('c'); ``` ### color(field: string, domain: IColor[]) `color` 方法支持简单的值映射,将根据 `field` 从传入图层的数据中提取的值映射到 `domain` 值域中。 ```js layer.color('type', ['#f00', '#0f0', '#00f']); ``` ### color(field: string, callback: () => IColor ) `color` 方法支持回调函数的写法,将根据 `field` 作为 `callback` 方法的参数,`callback` 方法的返回值作为图层实际的颜色。 ```js layer.color('type', (value) => { switch (value) { case 'water': return '#f00'; case 'wood': return '#0f0'; } }); ``` #### Scale - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/scale.md - Description: Scale --- title: "Scale" description: "Scale" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/scale/" --- `scale` 方法设置数据字段映射方法,用于设将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 ### scale(field: string, scaleConfig: IScaleConfig) - `field` 指定 source 中传入的数据中用于映射的字段名 - `scaleConfig` 列定义配置,对象类型 ```javascript interface IScaleConfig { type: ScaleTypeName; domain?: any[]; ... } layer.color('id', ['#f00', '#ff0']) .size('mag', [1, 80]) .scale('mag', { type: 'linear', domain: [ 1, 50] }); ``` ### ScaleTypeName `scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 `range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 | 数据类型 | 度量类型 | | -------- | ----------------------------------------------------------------- | | 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | | 分类 | cat、time | | 常量 | identity | #### Cat Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。 ```js // 三种作物会分别转成对应的颜色 // domain = ['corn','rice', 'soybean']; // range = ['red','white','blue']; const data = [ { lng: 120, lat: 30, t: 'corn' }, { lng: 121, lat: 30, t: 'rice' }, { lng: 122, lat: 30, t: 'soybean' }, ]; layer.source(data, { parser: { type: 'type', x: 'lng', y: 'lat', }, }); layer.scale('t', { type: 'cat' }); layer.color('t', ['red', 'white', 'blue']); ``` #### identify 常量度量 某个字段是不变的常量。 #### linear 线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色 #### quantize 相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量 #### quantile 每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。 由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。 #### threshold 他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数 手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准 ``` -1 => "red" 0 => "white" 0.5 => "white" 1.0 => "blue" 1000 => "blue ``` #### diverging || Sequential 用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 ```js const scaleColors = d3interpolate.interpolateRgbBasis(colors); ``` ### IScaleConfig ```js interface IScaleConfig { type: ScaleTypeName; domain?: any[]; range?: any[]; neutral?: number; field?: string; unknown?: string; ticks?: any[]; nice?: boolean; clamp?: boolean; format?: () => any; } ``` #### MVT Tile - Canonical page: https://l7.antv.antgroup.com/zh/api/source/mvt/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/mvt.md - Description: MVT Tile --- title: "MVT Tile" description: "MVT Tile" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/mvt/" --- L7 加载矢量瓦片地图的时候需要在 `source` 中对瓦片服务进行解析,同时配置瓦片服务的请求参数。 ## parser ### type _string_ **必选** _default:_ mvt ### tileSize `number` _number_ **可选** _default:_ 256 请求瓦片的大小 ### zoomOffset number **可选** _default:_ 0 瓦片请求瓦片层级的偏移 ### maxZoom _number_ **可选** _default:_ 0 瓦片最大缩放等级 `20` ### minZoom _number_ **可选** _default:_ 2- 瓦片最小缩放等 ### extent `[number, number, number, number]` _number[]_ **可选** 不限制:\_ 地图显示范围 ### getCustomData `(tile: { x: number, y: number, z: number }, callback: (err: any, data: any) => void) => void,` \_\_ **可选** callback 参数 - err 数据返回时 - data arrarybuffer 类型, pbf 自定义瓦片数据获取方法,试用业务场景需要数据鉴权,或者特殊处理的场景 ## 瓦片 source 属性 ### tileset 瓦片数据集,可以获取当前视野内的瓦片信息, 瓦片状态 ```ts const source = layer1.getSource(); const tileSet = source.tileset; ``` #### 属性 ##### isLoaded 瓦片是否加载完成 ##### currentTiles 当前瓦片对象 ##### currentZoom 当前瓦片层级;这里的曾经和map 的缩放层级不相等 #### 事件 ##### tiles-load-start 地图拖动,需要加载新的瓦片时触发 ```ts tileSet.on('tiles-load-start', () => { console.log('tile start'); }); ``` ##### tiles-load-finished 所有需要加载的瓦片资源加载完成后触发 ```ts tileSet.on('tiles-load-finished', () => { console.log('tile finished'); }); ``` ## 瓦片 source 方法 ### reloadAllTile 重新加载瓦片,会重新请求数据,适用与动态瓦片场景,如瓦片数据发生了更新,或者瓦片Join 的数据发生了更新 ```ts pure source.reloadAllTile(); ``` ### reloadTilebyId 重新加载特定瓦片的 参数 - z 缩放等级 - x 瓦片 x 坐标 - y 瓦片 y 坐标 ```ts pure source.reloadTileById(z, x, y); ``` ### reloadTileByExtent 根据经纬度范围更新瓦片 参数 - extent: 经纬范围 [minLng, minLat, maxLng, maxLat] - zoom: 缩放等级 ### reloadTileByLnglat 根据经纬度更新瓦片,经纬度坐标转换成瓦片坐标更新 - lng 经度 - lat 纬度 - zoom 缩放等级 ```tsx pure source.reloadTileByLnglat(112, 30, 10); ``` ## 示例 ### 通用 ```javascript const tileSource = new Source('http://localhost:3000/zhejiang.mbtiles/{z}/{x}/{y}.pbf', { parser: { type: 'mvt', tileSize: 256, zoomOffset: 0, maxZoom: 9, extent: [-180, -85.051129, 179, 85.051129], }, }); ``` ### 自定义方法 ```javascript const source = new Source('https://gridwise.alibaba-inc.com/tile/test?z={z}&x={x}&y={y}', { parser: { type: 'mvt', tileSize: 256, getCustomData: (tile, cb) => { const url = `https://gridwise.alibaba-inc.com/tile/test?z=${tile.z}&x=${tile.x}&y=${tile.y}`; fetch(url) .then((res) => res.arrayBuffer()) .then((data) => { cb(null, data); }); }, }, }); ``` #### ExportImage 导出图片 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/export-image/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/export-image.md - Description: ExportImage 导出图片 --- title: "ExportImage 导出图片" description: "ExportImage 导出图片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/export-image/" --- 对当前地图部分进行截图并生成图片的 `Base64` 字符串。 ## 说明 [示例](/zh/examples/component/control/exportimage/) 截图时被截取的目标仅包含: - 地图底图 - 图层(不包含 MarkerLayer) **注意:由于当前地图底图对应 `Canvas` 默认开启了缓冲区,导致默认情况下无法截取到地图底图部分。** 因此若开发者需要完整的截图能力,则应当在初始化地图实例时传递以下参数以关闭 `Canvas` 缓冲区。 ```ts new GaodeMapV2({ WebGLParams: { preserveDrawingBuffer: true, }, }); new Mapbox({ preserveDrawingBuffer: true, }); ``` ## 使用 ```ts import { Scene, ExportImage } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMapV2({ // 关闭地图缓冲区,否则截图时无法截取到地图部分 WebGLParams: { preserveDrawingBuffer: true, }, }), }); scene.on('loaded', () => { const zoom = new ExportImage({ onExport: (base64: string) => { // download(base64) }, }); scene.addControl(zoom); }); ``` ## 配置 | 名称 | 说明 | 类型 | | --------- | -------------------------------------------------- | -------------------------- | | imageType | 截图图片的格式 | `'png'` \| `'jpeg'` | | onExport | 截图成功后,用于接收图片 `Base64` 字符串的回调函数 | `(base64: string) => void` | | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------- | ----------------------------- | | btnIcon | 按钮图标 | `HTMLElement` \| `SVGElement` | | btnText | 按钮内容文本 | `string` | | title | 按钮的 `title` 属性 | `string` | | vertical | 在 btnIcon 有值的情况下,按钮内的图标和文案是否纵向排列 | `boolean` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | -------- | ------------------------ | ----------------------- | | getImage | 获取截图的 Base64 字符串 | `() => Promise` | | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### Animate - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/animate/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/animate.md - Description: Animate --- title: "Animate" description: "Animate" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/animate/" --- 线图层图层在开启 `animate` 方法后会得到沿线方向的线动画。 ### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` ### IAnimateOption ```javascript interface IAnimateOption { enable: boolean; speed: number; rings: number; } ``` ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) #### Animate - Canonical page: https://l7.antv.antgroup.com/zh/api/point_layer/animate/ - Markdown source: https://l7.antv.antgroup.com/zh/api/point_layer/animate.md - Description: Animate --- title: "Animate" description: "Animate" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/point_layer/animate/" --- 点图层在开启 `animate` 方法后根据点是 `2D` 点还是 `3D` 点支持两种不同的动画:水波点和生长动画。 点图层在开启 `animate` 方法后会得到特殊的水波图形。图层由一圈圈向外扩散的圆环构成。 ### 水波点 #### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` #### IAnimateOption ```javascript interface IAnimateOption { enable: boolean; speed: number; rings: number; } ``` ### 生长动画 #### animate(boolean | IAnimateOption) `animate` 方法支持布尔值和对象传值。 ```javascript animate(true) animate(false) animate(animateOptions) interface IAnimateOptions: { enable: boolean; speed?: number = 0.01; repeat?: number = 1; } ``` ``` #### IAnimateOptions `animate` 方法的参数: - `enable` 是否开启动画,布尔值,默认为 `false`。 - `speed` 生长速度,数值,默认为 `0.01`。 - `repeat` 生长动画的播放次数,数值,默认为 `1`。 ``` #### Animate - Canonical page: https://l7.antv.antgroup.com/zh/api/polygon_layer/animate/ - Markdown source: https://l7.antv.antgroup.com/zh/api/polygon_layer/animate.md - Description: Animate --- title: "Animate" description: "Animate" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/polygon_layer/animate/" --- 几何体图层在 `shape` 为 `water` 或 `ocean` 的时候会得到流动的水面,此时我们需要使用 `animate` 方法开启动画。 ### animate(boolean) `animate` 方法支持布尔值和对象传值。 ```javascript layer.animate(true); layer.animate({ enable: true, }); ``` #### Raster Tile - Canonical page: https://l7.antv.antgroup.com/zh/api/source/raster_tile/ - Markdown source: https://l7.antv.antgroup.com/zh/api/source/raster_tile.md - Description: Raster Tile --- title: "Raster Tile" description: "Raster Tile" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/source/raster_tile/" --- L7 加载栅格瓦片地图的时候需要在 `source` 中对瓦片服务进行解析,同时配置瓦片服务的请求参数。 ## data 瓦片 URL,仅支持 EPSG 3857 的坐标系,支持 TMS、WMS、WMTS 协议 ### TMS 通过 url 模板传参,参与需要使用 `{}` - 1-4 服务器编码 {1-4} - z 缩放等级 - x 瓦片 x 坐标 - y 瓦片 y 坐标 ```js const url = 'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'; ``` ### WMS url 模板参数 - 1-x 服务器编码 {1-4} - bbox 瓦片范围模板 BBOXSR 只支持 4326,IMAGESR 只支持 3857 示例 ```js const url = 'https://pnr.sz.gov.cn/d-suplicmap/dynamap_1/rest/services/LAND_CERTAIN/MapServer/export?F=image&FORMAT=PNG32&TRANSPARENT=true&layers=show:1&SIZE=256,256&BBOX={bbox}&BBOXSR=4326&IMAGESR=3857&DPI=90'; ``` ### WMTS url 模板参数 - 1-4 服务器编码 {1-4} WMTS 两种方式 - 使用方式和 TMS 相似,可以拼接 url 字符串 - 通过 parser 参数 wmtsOptions 设置服务参数 ```js const url1 = 'https://t0.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&'; const layer1 = new RasterLayer({ zIndex: 1, }).source(url1, { parser: { type: 'rasterTile', tileSize: 256, wmtsOptions: { layer: 'img', tileMatrixset: 'w', format: 'tiles', }, }, }); ``` ## parser ### type _string_ **必选** _default:_ rasterTile 固定值为 `rasterTile` ### tileSize `number` _number_ **可选** _default:_ 256 请求瓦片的大小 optional ### zoomOffset number **可选** _default:_ 0 瓦片请求瓦片层级的偏移 ### maxZoom _number_ **可选** _default:_ 0 瓦片最大缩放等级 `20` ### minZoom 瓦片最小缩放等 _number_ **可选** _default:_ 2- ### extent `[number, number, number, number]` 地图显示范围 _number[]_ **可选** 不限制:\_ ### dataType _string_ **可选** _default:_ image 瓦片数据类型 - image 图像类型 - arraybuffer 数据类型如 geotiff ### format func, _func_ **可选** \_default: 数据栅格时使用,用于将栅格数据格式化为标准数据,自定义数据处理函数 ### wmtsOptions wmsts 配置 _Object_ **可选** _default:_ null #### layer _string_ **必选** _default:_ img 图层 #### tileMatrixset _string_ **必选** _default:_ w #### format _string_ **必选** _default:_ tiles 服务类型 ```javascript const rasterSource = new Source( 'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 0, extent: [-180, -85.051129, 179, 85.051129], }, }, ); ``` ## 瓦片 source 属性 ### tileset 瓦片数据集,可以获取当前视野内的瓦片信息, 瓦片状态 ```ts const source = layer1.getSource(); const tileSet = source.tileset; ``` #### 属性 ##### isLoaded 瓦片是否加载完成 ##### currentTiles 当前瓦片对象 ##### currentZoom 当前瓦片层级;这里的曾经和map 的缩放层级不相等 #### 事件 ##### tiles-load-start 地图拖动,需要加载新的瓦片时触发 ```ts tileSet.on('tiles-load-start', () => { console.log('tile start'); }); ``` ##### tiles-load-finished 所有需要加载的瓦片资源加载完成后触发 ```ts tileSet.on('tiles-load-finished', () => { console.log('tile finished'); }); ``` ## 瓦片 source 方法 ### reloadAllTile 重新加载瓦片,会重新请求数据,适用与动态瓦片场景,如瓦片数据发生了更新,或者瓦片Join 的数据发生了更新 ```ts pure source.reloadAllTile(); ``` ### reloadTilebyId 重新加载特定瓦片的 参数 - z 缩放等级 - x 瓦片 x 坐标 - y 瓦片 y 坐标 ```ts pure source.reloadTileById(z, x, y); ``` ### reloadTileByExtent 根据经纬度范围更新瓦片 参数 - extent: 经纬范围 [minLng, minLat, maxLng, maxLat] - zoom: 缩放等级 ### reloadTileByLnglat 根据经纬度更新瓦片,经纬度坐标转换成瓦片坐标更新 - lng 经度 - lat 纬度 - zoom 缩放等级 ```tsx pure source.reloadTileByLnglat(112, 30, 10); ``` #### LayerSwitch 图层显隐 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/layer_switch/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/layer_switch.md - Description: LayerSwitch 图层显隐 --- title: "LayerSwitch 图层显隐" description: "LayerSwitch 图层显隐" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/layer_switch/" --- 用于控制目标图层组的**显示**和**隐藏**操作。 ## 说明 **注意**: 在控件中展示的图层名称会默认读取图层的 `name` 属性,因此需要用户在初始化图层时传入图层对应的名称。 ## 使用 [示例](/zh/examples/component/control/layerswitch/) ```ts import { Scene, LayerSwitch } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const layer = new PointLayer({ name: '自定义图层名称', }); scene.addLayer(layer); const layerSwitch = new LayerSwitch({ layers: [layer], }); scene.addControl(layerSwitch); }); ``` ## 配置 | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------------------------------------------ | -------------------------------------------- | | layers | 需要被控制的 `layer` 数组,支持传入图层示例或者图层 id,不传则默认读取当前 L7 中所有的图层 | `Array` | | multiple | 控件内的图层选项是否为多选,单选模式下默认展示第一个选项对应的图层 | `boolean` | ### LayerSwitchItem | 名称 | 说明 | 类型 | | ----- | ------------------------- | --------------------- | | layer | 需要被控制的 `layer` 实例 | `ILayer` | | name | 展示的图层名称 | `string \| undefined` | | img | 展示的图层图片 `URL` | `string \| undefined` | | 名称 | 说明 | 类型 | | --------------- | -------------------- | ----------------------------------- | | popperPlacement | 气泡相对于按钮的位置 | [PopperPlacement](#PopperPlacement) | | popperTrigger | 气泡弹出的触发方式 | `'click'` \| `'hover'` | | popperClassName | 气泡容器自定义样式名 | `string` | ### PopperPlacement ```ts export type PopperPlacement = | 'top-start' | 'top' | 'top-end' | 'left-start' | 'left' | 'left-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'right-start' | 'right' | 'right-end'; ``` | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------- | ----------------------------- | | btnIcon | 按钮图标 | `HTMLElement` \| `SVGElement` | | btnText | 按钮内容文本 | `string` | | title | 按钮的 `title` 属性 | `string` | | vertical | 在 btnIcon 有值的情况下,按钮内的图标和文案是否纵向排列 | `boolean` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | | 名称 | 说明 | 类型 | | ---------- | ---------------- | ---------------- | | popperShow | 气泡显示时的回调 | `(this) => void` | | popperHide | 气泡隐藏时的回调 | `(this) => void` | | 名称 | 说明 | 类型 | | ------------ | ---------------------- | -------- | ------------------ | | selectChange | 当所选值发生改变时触发 | `(string | string[]) => void` | #### Style - Canonical page: https://l7.antv.antgroup.com/zh/api/line_layer/style/ - Markdown source: https://l7.antv.antgroup.com/zh/api/line_layer/style.md - Description: Style --- title: "Style" description: "Style" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/line_layer/style/" --- `style` 方法用于配制图层的样式,相同图层拥有不同的 `shape` 图形,不同 `shape` 的图层 `style` 方法接受不同的参数。 ```js layer.style({ opacity: 0.5, }); ``` ### common 通用 `style` 参数,所有图形都支持的参数。 | style | 类型 | 描述 | 数据映射 | 默认值 | | ------- | -------- | ------------ | -------- | ------ | | opacity | `number` | 图形的透明度 | 支持 | `1` | ### line `shape` 为 `line` 的普通线图层。 - [line](/zh/api/line_layer/shape#shapeline) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------------------------- | -------------------------- | ------------ | ----------- | | stroke | `string` | 图形边框颜色 | 是 | `#fff` | | strokeWidth | `number` | 图形边框半径 | 否 | `0` | | blur | `[number, number, number]` | 图形模糊分布 | 否 | `[1, 1, 1]` | | raisingHeight | `number` | 抬升高度 | 否 | `0` | | heightfixed | `boolean` | 抬升高度是否随 `zoom` 变化 | 否 | `false` | ### arc `shape` 为 `arc` 平面的弧线。 - [arc](/zh/api/line_layer/shape#shapearc) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------- | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | thetaOffset | `number` | 弧线的弧度参数 | 是 | `0.314` | ### arc3d `shape` 为 `arc3d` 的弧线图层。 - [arc3d](/zh/api/line_layer/shape#shapearc3d) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------ | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | | thetaOffset | `number` | 弧线的弧度参数 | 是 | `1` | ### greatcircle `shape` 为大圆弧线图层。 - [greatcircle](/zh/api/line_layer/shape#shapegreatcircle) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) - [支持虚线](/zh/api/line_layer/style#dash) | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | -------- | ---------------------------------- | ------------ | ------ | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | segmentNumber | `number` | 弧线分段,分段越多越平滑,消耗越大 | 否 | `30` | ### flowline | style | 类型 | 描述 | 支持数据映射 | 默认值 | | ------------- | ----------------- | ------------------------ | ------------ | ------- | | opacity | `number` | 透明度,支持数据映射 | 是 | `1` | | strokeOpacity | `number` | 描边透明度 | 否 | `30` | | stroke | `number` | 描边颜色 | 是 | `#000` | | strokeWidth | `number` | 描边宽度 | `1` | 否 | | gapWidth | `number` | 不同方向两条线间距 | `2` | 否 | | offsets | `[number,number]` | 两端偏移量,支持数据映射 | 是 | `[0,0]` | flowline opacity 和 offsets 支持数据映射,数据驱动设置数据大小 #### opacity ```ts layer.style({ opacity: { field: 'count', // 映射字段 value: [0.2,0.4,0.6,0.8], // 映射值,支持回调函数,支持设置scale } // field 和 value 等同于 layer.color('count',[0.2,0.4,0.6,0.8]) ``` #### offsets ```ts layer.style({ offsets:{ field: 'count', values:() => { return [10 + Math.random()*20, 10 + Math.random()*20] } }) ``` ### wall `shape` 为 `wall` 地理围栏弧线图层。 - [wall](/zh/api/line_layer/shape#shapewall) - [支持渐变](/zh/api/line_layer/style#linear) - [支持纹理](/zh/api/line_layer/style#texture) ### simple `shape` 为 `simple` 简单线图层。 - [simple](/zh/api/line_layer/shape#shapesimple) - [支持渐变](/zh/api/line_layer/style#linear) ### linear - line、arc、arc3d、greatcircle、wall、simple 线图层支持配置渐变效果,在配置渐变效果后会覆盖 `layer.color` 方法设置的颜色。 | style | 类型 | 描述 | 默认值 | | ----------- | ------------ | ---------- | ---------- | | sourceColor | `IColor` | 线起始颜色 | `/` | | targetColor | `IColor` | 线结尾颜色 | `/` | | linearDir | `ILinearDir` | 线渐变方向 | `vertical` | #### IColor ```js const color = `rgb(200, 100, 50)`; const color2 = '#ff0'; ``` #### ILinearDir - vertical 纵向(沿线方向) - horizontal 横向 ```js type ILinearDir = 'vertical' | 'horizontal'; ``` ### texture - line、arc、arc3d、greatcircle 线图层支持纹理以及纹理动画,纹理样式有自己的参数。 | style | 类型 | 描述 | 默认值 | | ------------ | --------------- | ------------------------------ | -------- | | lineTexture | `boolean` | 时候开启纹理能力 | `false` | | textureBlend | `ITextureBlend` | 纹理混合方式 | `normal` | | iconStep | `number` | 纹理贴图在线图层上面排布的间隔 | `100` | #### ITextureBlend 线图层的纹理在和线本身的颜色进行融合的时候支持两种,`normal` 和 `replace`。 - normal 纹理和线颜色混合 - replace 使用纹理替换线颜色 ```js type ITextureBlend = 'normal' | 'replace'; ``` #### texture advance ✨ animate 当线图层 (shape 为 arc/arc3d) 开启动画模式的时候,纹理在线图层上的分布还会和 animate 的参数相关 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` ### dash - line、arc、arc3d、greatcircle 线图层支持配置虚线,虚线有自己额外的样式参数。 ```js layer.style({ lineType: 'dash' dashArray: [5, 5] }) ``` | style | 类型 | 描述 | 默认值 | | --------- | ------------ | ---------- | ------- | | lineType | `ILineType` | 线的类别 | `solid` | | dashArray | `IDashArray` | 虚线的间隔 | `/` | #### ILineType - solid 实线 - dash 虚线 #### IDashArray `dashArray` 只有在 `ILineType` 为 `dashed` 的时候才会生效。 ```js // len1 实线长度 len2 间隔长度 type IDashArray = [len1: number, len2: number] ``` #### MouseLocation 光标经纬度 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/mouse_location/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/mouse_location.md - Description: MouseLocation 光标经纬度 --- title: "MouseLocation 光标经纬度" description: "MouseLocation 光标经纬度" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/mouse_location/" --- 用于实时展示当前光标在地图上所对应的经纬度。 ## 使用 [示例](/zh/examples/component/control/mouselocation/) ```ts import { Scene, MouseLocation } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const mouseLocation = new MouseLocation({ transform: (position) => { return position; }, }); scene.addControl(mouseLocation); }); ``` ## 配置 | 名称 | 说明 | 类型 | | --------- | ---------------------------- | -------------------------------------------------- | | transform | 转换光标所在经纬度的回调函数 | `(position: [number, number]) => [number, number]` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | -------------- | ---------------------------- | -------------------------------------- | | locationChange | 光标所在经纬度发生变化时触发 | `(position: [number, number]) => void` | | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | #### 后处理模块 - Canonical page: https://l7.antv.antgroup.com/zh/api/experiment/pass/ - Markdown source: https://l7.antv.antgroup.com/zh/api/experiment/pass.md - Description: 后处理模块 --- title: "后处理模块" description: "后处理模块" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/experiment/pass/" --- 后处理(Post-Process Effect)是 3D 渲染常见的处理效果,是一种对渲染之后的画面进行再加工的技术,一般用于实现各种特效。L7 的后处理模块为用户提供了一些常见的后处理效果,同时也提供了标准规范,允许用户自定义后处理效果。 🌟 需要注意的是,使用后处理通常会产生额外的性能消耗,用户应该根据项目的实际情况合理使用后处理。 ## 使用 ```jsx const layer = new LineLayer({ enableMultiPassRenderer: true, passes: [ [ 'bloom', { bloomBaseRadio: 0.8, bloomRadius: 2, bloomIntensity: 1 } ] ] }).source(data) .size('ELEV', h => [ h % 50 === 0 ? 1.0 : 0.5, (h - 1300) * 0.2 ]) .shape('line') .scale('ELEV', { type: 'quantize' }) .color('ELEV', [ '#094D4A', ... ]); scene.addLayer(layer); ``` ### 开启后处理 为了开启图层的后处理能力,我们需要在初始化图层的时候配置 enableMultiPassRenderer 为 true,同时传入该图层作用的处理效果配置。 ```javascript let pointLayer = new PointLayer({ zIndex: 1, enableMultiPassRenderer: false, passes: [ [ 'bloom', { bloomBaseRadio: 0.95, bloomRadius: 4, bloomIntensity: 1.1, }, ], ], }); ``` - enableMultiPassRenderer 配置该图层是否开始后处理能力 - passes 后处理配置列表 🌟 passes 需要根据一定的规则配置 ### 单图层后处理 传统的后处理渲染往往会对场景中所有的对象做统一的后处理,而许多时候我们只需要对场景中的一部分内容做后处理。L7 的后处理模块天然支持以图层为单位进行后处理,这使的用户对 L7 场景内容的处理有更高的自由度。 ### update pass options 用户在初始化完图层对象之后,若想调整后处理效果的参数,可以直接使用 style 方法 ```javascript layer.style({ passes: [ [ 'colorHalftone', { // 更新 cenrter 的位置 center: [newX, newY], }, ], ], }); scene.render(); ``` ### setMultiPass(enableMultiPassRenderer: boolean, passes?: pass[]) 为了方便用户切换后处理的状态(开启、关闭后处理),我们为用户提供了专门的方法 ```javascript // 当前图层存在 multiPass,我们需要关闭时 // 直接关闭 layer.setMultiPass(false); // 关闭的同时清除 passes layer.setMultiPass(false, []); // 当前图层不存在 multiPass,我们需要开启时 // 图层初始化时已经传入 passes const layer = new PolygonLayer({ zIndex: 0, enableMultiPassRenderer: false, passes: [ [ 'bloom', { bloomBaseRadio: 0.5, bloomRadius: 20, bloomIntensity: 1, }, ], ], }); layer.setMultiPass(true); // 图层初始化时没有传入 passes layer.setMultiPass(true, [ [ 'bloom', { bloomRadius: 10, bloomIntensity: 1, }, ], ]); ``` ### 后处理链路 passes 可以传入多种后处理,普通渲染的结果是第一个后处理的输入,前一种后处理的输出是后一个后处理的输入,最后的结果输出到屏幕。 ### 预制的后处理 L7 的后处理模块预置了几种后处理效果,因此用户可以直接在 passes 中配置使用。 #### bloom ```javascript const bloomPass = [ 'bloom', { bloomBaseRadio: 0.5, bloomRadius: 20, bloomIntensity: 1, }, ]; ``` 辉光后处理 - bloomBaseRadio 设置保持图形原本样式的比例,值在 0 - 1 之间,值为 1 时完全保存本身的样式 - bloomRadius 设置 bloom 的半径,值越大,bloom 范围越大 - bloomIntensity 设置 bloom 的强度,值越大,辉光越强 #### blurV/blurH 垂直方向模糊/水平方向模糊 ```javascript const blurVPass = [ 'blurV', { blurRadius: 5, }, ]; const blurHPass = [ 'blurH', { blurRadius: 5, }, ]; ``` - blurRadius 设置模糊半径 #### colorHalftone colorHalftone ```javascript const colorHalftonePass = [ 'colorHalftone', { angle: 0, size: 8, centerX: 0.5, centerY: 0.5, }, ]; ``` - angle 设置角度 - size 设置大小 - centerX 设置中心点 X - centerY 设置中心点 Y #### hexagonalPixelate 六边形像素 ```javascript const hexagonalPixelatePass = [ 'hexagonalPixelate', { scale: 10, centerX: 0.5, centerY: 0.5, }, ]; ``` - scale 设置缩放 - centerX 设置中心点 X - centerY 设置中心点 Y #### ink ink ```javascript const inkPass = [ 'ink', { strength: 1, }, ]; ``` - strength 设置强度 #### noise 噪声 ```javascript const noisePass = [ 'noise', { amount: 1, }, ]; ``` - amount 设置噪点数量 ### 自定义后处理 用户通过 L7 定义的标准可以轻松的自定义后处理效果。 ```javascript import { BasePostProcessingPass, PolygonLayer, Scene } from '@antv/l7'; interface IDotScreenEffectConfig { center: [number, number]; // pattern 圆心 angle: number; // dot 旋转角度 size: number; // dot 尺寸 } class DotScreenEffect extends BasePostProcessingPass { protected setupShaders() { this.shaderModuleService.registerModule('dotScreenEffect', { vs: this.quad, fs: ` varying vec2 v_UV; uniform sampler2D u_Texture; uniform vec2 u_ViewportSize : [1.0, 1.0]; uniform vec2 u_Center : [0.5, 0.5]; uniform float u_Angle : 1; uniform float u_Size : 3; float pattern(vec2 texSize, vec2 texCoord) { float scale = 3.1415 / u_Size; float s = sin(u_Angle), c = cos(u_Angle); vec2 tex = texCoord * texSize - u_Center * texSize; vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale; return (sin(point.x) * sin(point.y)) * 4.0; } vec4 dotScreen_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { float average = (color.r + color.g + color.b) / 3.0; return vec4(vec3(average * 10.0 - 5.0 + pattern(texSize, texCoord)), color.a); } void main() { gl_FragColor = vec4(texture2D(u_Texture, v_UV)); gl_FragColor = dotScreen_filterColor(gl_FragColor, u_ViewportSize, v_UV); } `, }); const { vs, fs, uniforms } = this.shaderModuleService.getModule('dotScreenEffect'); const { width, height } = this.rendererService.getViewportSize(); return { vs, fs, uniforms: { ...uniforms, u_ViewportSize: [width, height], }, }; } } // 注册自定义后处理效果 scene.registerPostProcessingPass(DotScreenEffect, 'dotScreenEffect'); const layer = new PolygonLayer({ enableMultiPassRenderer: true, passes: [ [ 'dotScreenEffect', { size: 8, angle: 1, }, ], ], }); ``` #### 天地图 - Canonical page: https://l7.antv.antgroup.com/zh/api/map/tianditu/ - Markdown source: https://l7.antv.antgroup.com/zh/api/map/tianditu.md - Description: 天地图 --- title: "天地图" description: "天地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/map/tianditu/" --- ## 简介 L7 地理可视化侧重于地理数据的可视化表达,地图层需要依赖第三方地图,第三方地图通过 Scene 统一创建管理,只需要通过 Scene 传入地图配置项即可。 L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。 - [天地图 官网](http://lbs.tianditu.gov.cn/api/js4.0/guide.html) ## 申请 token 天地图 JavaScript API 4.0 支持 HTTP 和 HTTPS,免费对外开放,可直接使用。使用 API 之前,需要[申请应用 Key](https://console.tianditu.gov.cn/api/key)。 ## import ```javascript import { TdtMap } from '@antv/l7-maps'; ``` ## 使用 ```ts import { Scene } from '@antv/l7'; import { TdtMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new TdtMap({ token: '你的天地图 token', center: [120, 30], zoom: 10, }), }); scene.on('loaded', () => { // 添加图层 }); ``` ## 配置项 | 名称 | 说明 | 类型 | 默认值 | | ----------- | -------------------- | ------------------ | -------------------------------- | | token | 天地图 API 的 Key | `string` | 内置测试 token(生产环境请替换) | | center | 地图初始中心经纬度 | `[number, number]` | `[121.30654, 31.25744]` | | zoom | 地图初始缩放等级 | `number` | `3` | | minZoom | 地图最小缩放等级 | `number` | `1` | | maxZoom | 地图最大缩放等级 | `number` | `18` | | mapInstance | 传入已有的天地图实例 | `T.Map` | - | ## options ### zoom 初始化缩放等级 _number_ 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19) ### center 地图中心 地图初始中心经纬度 {Lnglat} ### pitch 地图倾角 地图初始俯仰角度 {number} default 0 ### bearing 地图偏转角 地图初始旋转角度(相对于正北方向顺时针偏转的度数) {number} default 0 ### minZoom 最小缩放等级 地图最小缩放等级 {number} default 0 Mapbox 0-24) 高德 (2-19) ### maxZoom 最大缩放等级 地图最大缩放等级 {number} default 22 Mapbox(0-24) 高德 (2-19) ### minPitch 最小倾角 地图最小俯仰角 {number} default 0 ### maxPitch 最大倾角 地图最大俯仰角 {number} default 60 ### rotateEnable 是否允许旋转 地图是否可旋转 {Boolean} default true ### interactive 是否允许交互 _boolean_ **optional** _default:_ true 是否允许地图交互(包括鼠标、触摸、键盘等),设为 `false` 后地图变为静态展示状态 ### scrollZoom 是否允许滚轮缩放 _boolean_ **optional** _default:_ true 是否启用滚轮缩放交互 ### boxZoom 是否允许框选缩放 _boolean_ **optional** _default:_ true 是否启用框选缩放交互(按住 Shift 拖拽) ### dragRotate 是否允许拖拽旋转 _boolean_ **optional** _default:_ true 是否启用拖拽旋转交互 ### dragPan 是否允许拖拽平移 _boolean_ **optional** _default:_ true 是否启用拖拽平移交互 ### keyboard 是否允许键盘控制 _boolean_ **optional** _default:_ true 是否启用键盘快捷键控制地图 ### doubleClickZoom 是否允许双击缩放 _boolean_ **optional** _default:_ true 是否启用双击缩放交互 ### touchZoomRotate 是否允许触摸缩放旋转 _boolean_ **optional** _default:_ true 是否启用双指捏合缩放旋转交互 ### renderWorldCopies 是否渲染世界副本 _boolean_ **optional** _default:_ true 超出 -180 和 180 经度范围时,是否在两侧重复渲染地图 ### maxBounds 地图最大边界范围 限制地图可视范围在指定的地理范围内 ### bearingSnap 北向吸附阈值 _number_ **optional** _default:_ 7 当用户旋转地图接近正北方向时,自动吸附到正北方向的角度阈值(度数) ## 地图事件 Scene 统一代理,见 [Scene 文档](/zh/api/scene) 或者 scene.map 直接调用 map 实例方法 #### MapTheme 地图主题 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/map_theme/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/map_theme.md - Description: MapTheme 地图主题 --- title: "MapTheme 地图主题" description: "MapTheme 地图主题" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/map_theme/" --- 该控件用于切换地图底图的主题样式。 ## 说明 MapTheme 会根据当前地图底图类型(如 Mapbox、GaodeMapV2),默认展示相对应的默认主题选项,用于也可以传入自定义的主题选项 ## 使用 [示例](/zh/examples/component/control/maptheme/) ```ts import { Scene, MapTheme } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const mapTheme = new MapTheme({}); scene.addControl(mapTheme); }); ``` ## 配置 | 名称 | 说明 | 类型 | | ------- | -------------------------------------------------------------------------------------- | --------------------------- | | options | 用户自定义的地图主题选项,每个选项的类型可见 [IControlOptionItem](#icontroloptionitem) | `Array` | ## IControlOptionItem ```ts export type IControlOptionItem = { // 主题选项对应的文本 text: string; // 主题选项对应地图主题 style 的 key 值 value: string; // 主题选项对应展示的图片 img?: string; }; ``` | 名称 | 说明 | 类型 | | --------------- | -------------------- | ----------------------------------- | | popperPlacement | 气泡相对于按钮的位置 | [PopperPlacement](#PopperPlacement) | | popperTrigger | 气泡弹出的触发方式 | `'click'` \| `'hover'` | | popperClassName | 气泡容器自定义样式名 | `string` | ### PopperPlacement ```ts export type PopperPlacement = | 'top-start' | 'top' | 'top-end' | 'left-start' | 'left' | 'left-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'right-start' | 'right' | 'right-end'; ``` | 名称 | 说明 | 类型 | | -------- | ------------------------------------------------------- | ----------------------------- | | btnIcon | 按钮图标 | `HTMLElement` \| `SVGElement` | | btnText | 按钮内容文本 | `string` | | title | 按钮的 `title` 属性 | `string` | | vertical | 在 btnIcon 有值的情况下,按钮内的图标和文案是否纵向排列 | `boolean` | | 名称 | 说明 | 类型 | | --------- | ----------------------------------------------------------------------------------------- | --------------------- | | position | 控件被添加到地图中的位置以及排列方式,详情可见 [控件插槽](/zh/api/component/control#插槽) | [Position](#position) | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ### Position ```ts export type Position = | 'topleft' // ↖ 左上角,纵向排列 | 'lefttop' // ↖ 左上角,横向排列 | 'topright' // ↗ 右上角,纵向排列 | 'righttop' // ↗ 右上角,横向排列 | 'bottomleft' // ↙ 左下角,纵向排列 | 'leftbottom' // ↙ 左下角,横向排列 | 'bottomright' // ↘ 右下角,纵向排列 | 'rightbottom' // ↘ 右下角,横向排列 | 'topcenter' // ↑ 上方中央,横向排列 | 'bottomcenter' // ↓ 下方中间,横向排列 | 'leftcenter' // ← 左边中间,纵向排列 | 'rightcenter' // → 右边中间,纵向排列 | Element; // 传入 DOM 作为当前控件的容器 ``` ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | | 名称 | 说明 | 类型 | | ---------- | ---------------- | ---------------- | | popperShow | 气泡显示时的回调 | `(this) => void` | | popperHide | 气泡隐藏时的回调 | `(this) => void` | | 名称 | 说明 | 类型 | | ------------ | ---------------------- | -------- | ------------------ | | selectChange | 当所选值发生改变时触发 | `(string | string[]) => void` | #### Swipe 卷帘 - Canonical page: https://l7.antv.antgroup.com/zh/api/component/swipe/ - Markdown source: https://l7.antv.antgroup.com/zh/api/component/swipe.md - Description: Swipe 卷帘 --- title: "Swipe 卷帘" description: "Swipe 卷帘" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/api/component/swipe/" --- 该控件用于分屏对比两个地图上叠加图层。 ## 说明 图层可以添加到地图的左侧(顶部)或右侧(底部)。未添加到卷帘上的图层将显示在两侧。 ## 使用 [示例](/zh/examples/component/control/swipe/) ```ts import { Scene, Swipe } from '@antv/l7'; const scene = new Scene({ // ... }); scene.on('loaded', () => { const swipe = new Swipe({ orientation: 'vertical', ratio: 0.5, layers: [], rightLayers: [], }); scene.addControl(swipe); }); ``` ## 配置 | 名称 | 说明 | 类型 | | ----------- | ------------------------------------------- | -------------------------- | | orientation | 卷帘方向设置,默认 'vertical' | `'vertical'|'horizontal'` | | ratio | 卷帘的位置,值域为 0 到 1, 默认正中间为 0.5 | `number` | | layers | 卷帘左侧(竖向)或顶部(横向)的图层 | `ILayer[]` | | rightLayers | 卷帘右侧(竖向)或底部(横向)的图层 | `ILayer[]` | | className | 自定义样式名 | `string` | | style | 自定义样式 | `string` | ## 方法 | 名称 | 说明 | 类型 | | ------------ | --------------------------------------------- | -------------------------------------- | | setOptions | 更新配置,参数需要参考对应组件的[配置](#配置) | `(newOption: Partial) => void` | | getOptions | 获取当前[配置](#配置) | `() => Option` | | show | 显示组件 | `() => void` | | hide | 隐藏组件 | `() => void` | | getContainer | 获取当前控件对应的 `DOM` 容器 | `() => HTMLElement` | | 名称 | 说明 | 类型 | | ------------ | ---------------- | ---------------------------------------------------------------- | | addLayer | 添加要剪裁的图层 | `(layer: ILayer | ILayer[], addRight: boolean = false) => void` | | removeLayer | 移除剪裁的图层 | `(layer: ILayer | ILayer[]) => void` | | removeLayers | 清除所有图层 | `() => void` | ## 事件 | 名称 | 说明 | 类型 | | ------ | ------------------ | ---------------- | | add | 组件被添加时的事件 | `(this) => void` | | remove | 组件被移除时的事件 | `(this) => void` | | show | 组件显示时的事件 | `(this) => void` | | hide | 组件隐藏时的事件 | `(this) => void` | | 名称 | 说明 | 类型 | | ------ | ------------ | --------------------------------------------------- | | moving | 卷帘移动事件 | `(data: {size: number[], ratio: number[]}) => void` | ### tools #### 行政区划数据 - Canonical page: https://l7.antv.antgroup.com/zh/tools/ - Markdown source: https://l7.antv.antgroup.com/zh/tools.md - Description: 行政区划数据 --- title: "行政区划数据" description: "行政区划数据" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tools/" --- # 行政区划 一站式行政区划数据下载、应用平台 地图下载 GITHUB ## 特性 💎数据下载符合民政部数据规格,省、市、县三级数据,提供历史版本数据。 🧳完备提供在线可视化下载、数据 SDK、数据服务和可视化组件,满足不同的数据应用需求。 💾方便提供 GeoJSON、JSON、TopoJSON、CSV、KML 多种数据下载方式,以及 SVG 格式图像下载。 ## 数据字段 [Interactive content]() ## 谁在使用 AntV L7 L7Draw LarkMap L7VP #### 中国地图下载 - Canonical page: https://l7.antv.antgroup.com/zh/tools/map/ - Markdown source: https://l7.antv.antgroup.com/zh/tools/map.md - Description: 中国地图下载 --- title: "中国地图下载" description: "中国地图下载" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tools/map/" --- [Interactive content]() # 中国地图下载 选择行政区划、数据版本和坐标系,下载地理数据或 SVG。 [Interactive content]() #### 世界地图下载 - Canonical page: https://l7.antv.antgroup.com/zh/tools/worldmap/ - Markdown source: https://l7.antv.antgroup.com/zh/tools/worldmap.md - Description: 世界地图下载 --- title: "世界地图下载" description: "世界地图下载" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tools/worldmap/" --- [Interactive content]() # 世界地图下载 选择行政区划、数据版本和坐标系,下载地理数据或 SVG。 [Interactive content]() #### 数据 SDK - Canonical page: https://l7.antv.antgroup.com/zh/tools/sdk/ - Markdown source: https://l7.antv.antgroup.com/zh/tools/sdk.md - Description: 数据 SDK --- title: "数据 SDK" description: "数据 SDK" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tools/sdk/" --- [Interactive content]() ## 简介 DistrictData SDK 通过前端 JS SDK 更好的使用行政区划,无需下载数据, 数据服务托管在 npm 服务器。 ## 数据源介绍 ### RDBSource 基于于权威的行政区划数据,制作的一套 2015 年-2022 年的长时间序列的、具有符合民政部属性的、开放获取的行政区划数据 ## 安装 ### npm 安装 ```bash npm i district-data ``` ### cdn 引用 ```html ``` ### 添加 div 标签指定地图容器 同时需要为 `div`设置 高度和宽度。 ```html ``` ### 初始化 L7 Scene ```javascript const scene = new L7.Scene({ id: 'map', map: new L7.GaodeMap({ style: 'dark', // 样式URL center: [120.19382669582967, 30.258134], pitch: 0, zoom: 12, token: '高德地图token', }), }); ``` 这样我们就完成了通过 `L7` 实例化高德地图。 ### 添加可视化图层 - 首先我们需要获取数据,获取数据方法,这里我们获取在线的地理数据。 - 然后我们就可以初始一个 `Layer`,并添加到 `Scene` 就完成了图层的添加。 ```javascript fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') .then((res) => res.json()) .then((data) => { const pointLayer = new L7.PointLayer({}) .source(data.list, { parser: { type: 'json', x: 'j', y: 'w', }, }) .shape('cylinder') .size('t', function (level) { return [1, 2, level * 2 + 20]; }) .color('t', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#CEF8D6', ]); scene.addLayer(pointLayer); }); ``` ### 完整 demo 代码 ```html 创建地图场景 ``` #### MapBox 地图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/mapbox/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/mapbox.md - Description: MapBox 地图 --- title: "MapBox 地图" description: "MapBox 地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/mapbox/" --- ## 使用Mapbox 地图 1、注册MapBox token 注册地址 [Mapbox Access Tokens](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/#creating-and-managing-access-tokens) 2、引入mapbox.gl JS 和 css 使用mapbox 需要单独引入 mapbox ```html ``` ### 引入 L7 ```html ``` #### 添加div 标签指定地图容器 同时需要为Div设置 高度和宽度 ```html ``` ### 初始化 L7 Scene ```javascript const scene = new L7.Scene({ id: 'map', map: new L7.Mapbox({ style: 'dark', // 样式URL center: [120.19382669582967, 30.258134], pitch: 0, zoom: 12, token: 'mapbox token', }), }); ``` 这样我们就完成了通过L7 实例化mapbox地图 ### 添加可视化图层 ```javascript fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') .then((res) => res.json()) .then((data) => { const pointLayer = new L7.PointLayer({}) .source(data.list, { parser: { type: 'json', x: 'j', y: 'w', }, }) .shape('cylinder') .size('t', function (level) { return [1, 2, level * 2 + 20]; }) .color('t', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#CEF8D6', ]) .style({ opacity: 1.0, }); scene.addLayer(pointLayer); }); ``` ### 完整demo 代码 ```html 创建地图场景 ``` #### Use Offline - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/offline/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/offline.md - Description: Use Offline --- title: "Use Offline" description: "Use Offline" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/offline/" --- 目前 `L7` 支持高德和 `Mapbox` 两种底图,高德地图由于使用在线 `API` 不能做离线部署,如果你有离线部署的需求可以采用 `MapBox`做底图。`L7` 在接口层统一了不同底图直接的差异,一套可视化代码可以运行在 `L7` 支持的任意底图上。本文主要介绍如何离线使用,国内加速使用 `MapBox`,同时也提供了在线的字体服务,你也可也下载到本地使用。 ### L7 如何引入 Mapbox ```javascript import { Scene, LineLayer } from '@antv/l7'; import { Mapbox } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'dark', center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, token: 'xxxx', }), }); ``` ### 为什么离线化 - 离线部署 - 国内加速 - 不使用 `mapbox token` ### 如何离线化使用 MapBox 你只要不使用 `MapBox` 的数据底图服务就可以离线使用,`mapbox` 所有数据服务资源都是在 `style` 里面配置的。除了数据服务以外还有一些静态资源,这些主要是图片标注,文字标注的时候使用。 `mapbox` 本身数据资源在国外如果在国内单独部署使用,加载速度体验还是很好的。 我们先了解一下 `MapBox` 样式包含哪些配置项。 #### Mapbox 样式参数 - `version`:`JS SDK` 对应版本必须为 8。 - `name`:样式的命名。 - `sprite`:雪碧图,将一个地图涉及到的所有零星图标图片都包含到一张大图中。 - `glyphs`:`.pbf` 格式的字体样式,例如微软雅黑等字体库。 - `sources`:图层的资源文件,可以支持矢量切片、栅格、`dem` 栅格、图片、`geojson`、视频等格式。 - `layers`:是对每个图层样式的描述,这里就是对地图样式渲染的关键,可以做定制化地图样式。 具体参数及其 `api` 可以参考 `mapbox` 官网。 如果做到本地化只需要 `sprite`,`glyphs` 本地化就可以了,地图服务可以加载其他服务。 如果你不需要使用 `MapBox` 数据服务,可视化层完成用 `L7` 渲染那就更简单了。 你只需要将 `MapBox` 的地图样式设置 `blank`。 ```javascript const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'blank', center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, }), }); ``` `blank` 样式以为无底图样式,这种样式下就不需要使用 `mapbox` 服务,也不需要使用 `mapbox` 的 `token`。 #### 本地化雪碧图 如果你需要使用 `mapbox` 字段的图片标注,你需要本地化雪碧图资源只需要下载两个文件即可sprite.json 主要记录每个图表在大图上位置sprite.png 每个小图标组成的大图 在线雪碧图服务地址:[https://lzxue.github.io/font-glyphs/sprite/sprite](https://lzxue.github.io/font-glyphs/sprite/sprite) #### 本地化字体 如果需要使用 `mapbox` 文章标注功能需要本地化,如果你的渲染能力都是用 `L7` 实现的,这个过程也是不需要的。 `L7` 提供了在线字体服务 目前支持4种字体。 - 阿里巴巴普惠体 - noto - opensan - roboto _如果你有新的字体需求可提PR,帮你自动生成在线可用的字体服务,你可以在线使用,也可以下载到本地使用。_ 字体服务下载:[gh-pages分支](https://github.com/lzxue/font-glyphs/tree/gh-pages) 你可以 `clone` 下来直接使用。 **你也可以使用在线服务**github服务[https://lzxue.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf](https://lzxue.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf)蚂蚁CDN:[https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf](https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf) #### 地图服务本地化 1.加载[第三方底图](https://github.com/htoooth/Leaflet.ChineseTmsProviders),栅格瓦片图层做底图,如天地图,高德,`google` 的栅格瓦片都可以 2.下载[opensteetmap ](https://openmaptiles.com/downloads/planet/)矢量瓦片地图做底图 3.自己业务数据发布底图服务,或者矢量瓦片服务。 **这里还有个更完备的解决方案** [https://jingsam.github.io/foxgis-server-lite/#/](https://jingsam.github.io/foxgis-server-lite/#/) #### 所有的服务资源已经准备好了,这样我们就可以独立使用 `mapbox` 服务,不需要再申请 `mapbox` 的 `token`。 ```javascript import { Scene, LineLayer } from '@antv/l7'; import { Mapbox } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Mapbox({ style: { version: 8, name: 'blank', sprite: 'https://lzxue.github.io/font-glyphs/sprite/sprite', glyphs: 'https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf', sources: {}, layers: [ { id: 'background', type: 'background', paint: { 'background-color': 'white', }, }, ], }, center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, token: 'xxxx', }), }); ``` [离线,无token使用mapbox demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark) #### 气泡图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/bubble/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/bubble.md - Description: 气泡图 --- title: "气泡图" description: "气泡图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/bubble/" --- 气泡图地理区域上方会显示不同大小的圆点,圆形面积与其在数据集中的数值会成正比。 ### 实现 下面我们来介绍如何绘制一个常见的气泡图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/bubble/point/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [140.067171, 36.26186], zoom: 5.32, maxZoom: 10, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data) .shape('circle') .size('mag', [1, 25]) .color('mag', (mag) => { return mag > 4.5 ? '#5B8FF9' : '#5CCEA1'; }) .style({ opacity: 0.3, strokeWidth: 1, }); scene.addLayer(pointLayer); }); }); ``` ### source 气泡图接受普通的点数据。 ### shape 气泡图的 `shape` 一般为 `circle`,也可以是 `square`、`triangle` 等其他形状。 ### size 气泡图的 `size` 一般用于表示数据中的某个字段,因此不会使用常量而是使用数据映射。 ```js layer.size('area', [1, 100]); // 使用区间映射 layer.size('area', (area) => { // 使用回调函数实现映射 return area * 10; }); ``` ### color 气泡图的 `color` 一般也会用于表示数据中的某个字段,因此不会使用常量而是使用数据映射。 ```js layer.color('area', ['#f00', '#ff0']); // 使用区间映射 layer.color('area', (area) => { // 使用回调函数实现映射 if (area > 100) { return '#f00'; } else { return '#ff0'; } }); ``` #### 填充图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/polygon/fill/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/polygon/fill.md - Description: 填充图 --- title: "填充图" description: "填充图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/polygon/fill/" --- 几何体图层在地图上最简单的表现就是填充图,即使用指定的颜色填充指定区域。 ### 实现 下面我们来介绍如何绘制一个简单的填充图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/polygon/fill/usa/) ```javascript import { Scene, PolygonLayer, LineLayer, Popup } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [-96, 37.8], zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/d36ad90e-3902-4742-b8a2-d93f7e5dafa2.json') .then((res) => res.json()) .then((data) => { const color = [ 'rgb(255,255,217)', 'rgb(237,248,177)', 'rgb(199,233,180)', 'rgb(127,205,187)', 'rgb(65,182,196)', 'rgb(29,145,192)', 'rgb(34,94,168)', 'rgb(12,44,132)', ]; const layer = new PolygonLayer({}) .source(data) .scale('density', { type: 'quantile', }) .color('density', color) .shape('fill') .active(true); const layer2 = new LineLayer({ zIndex: 2, }) .source(data) .color('#fff') .active(true) .size(1) .style({ lineType: 'dash', dashArray: [2, 2], }); scene.addLayer(layer); scene.addLayer(layer2); }); }); ``` ### source 几何体图层推荐使用标准的 `GeoJSON` 数据。 ### shape 绘制填充图,shape 为 `fill` 常量,不支持数据映射 ```javascript layer.shape('fill'); ``` ### size 填充图不需要设置 `size`; ### style - `opacityLinear` 设置几何填充图的径向渐变。 ```javascript style({ opacityLinear: { enable: true, // true - false dir: 'in', // in - out }, }); ``` [径向渐变 in](/zh/examples/polygon/fill/linear-in/) [径向渐变 out](/zh/examples/polygon/fill/linear-out/) - `raisingHeight` 设置 `3D` 填充图的抬升高度。 #### 瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/tile/tile/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/tile/tile.md - Description: 瓦片 --- title: "瓦片" description: "瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/tile/tile/" --- 瓦片图层相比于普通的图层而言,在使用上有许多需要注意的地方。 ### option 在初始化瓦片的时候,除了普通图层支持的 `options` 参数之外,还需要需要我们提前设置矢量数据相关的参数。 - `featureId`: string - 用于可以自定义指定。用于指定瓦片的拾取高亮。 - `sourceLayer`: string - 用于必须传入,且要在返回的矢量数据中存在,指定绘制矢量数据中那一图层数据。 ```javascript const layer = new RasterLayer({ featureId: 'id', sourceLayer: 'water', }); ``` #### Mask 瓦片图层的掩模使用和普通的图层一样,同样在 `options` 中设置 `mask、maskfence` 参数即可,不过矢量瓦片图层暂时不支持设置掩模。 ```js fetch('https://gw.alipayobjects.com/os/bmw-prod/fccd80c0-2611-49f9-9a9f-e2a4dd12226f.json') .then((res) => res.json()) .then((maskData) => { const layer = new RasterLayer({ mask: true, maskfence: maskData, }); const tileSource = new Source( 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff', { parser: { type: 'rasterTile', dataType: 'arraybuffer', tileSize: 256, maxZoom: 13.1, format: async (data) => { const tiff = await GeoTIFF.fromArrayBuffer(data); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { rasterData: values[0], width, height }; }, }, }, ); layer.source(tileSource).style({ domain: [0.001, 11.001], clampLow: false, rampColors: { colors: colorList, positions, }, }); scene.addLayer(layer); }); ``` ### source 在有些场景下,尤其是是矢量瓦片地图的场景,同一份瓦片数据会同时包含多图层的数据,此时我们需要让多图层复用同一个 `source` 对象。如下图所示,我们使用同一份数据绘制省市的面、边界和名称,此时我们就应该复用 `source` 对象。 ```javascript const tileSource = new Source( 'http://localhost:3000/file.mbtiles/{z}/{x}/{y}.pbf', { parser: { type: 'mvt', tileSize: 256, zoomOffset: 0, maxZoom: 9, extent: [-180, -85.051129, 179, 85.051129], }, }); const option = { featureId: 'NAME_CHN', sourceLayer: 'city' } const linelayer = new LineLayer(option) .source(tileSource) .color('#f00') .size(1) .style({ opacity: 0.5, }); this.scene.addLayer(linelayer); const polygonlayer = new PolygonLayer(option) .source(tileSource) .color('citycode', (v: string) => { return getRandomColor(v); } }) .style({ opacity: 0.4, }) .select(true); this.scene.addLayer(polygonlayer); const pointlayer = new PointLayer(option) .source(tileSource) .shape('NAME_CHN', 'text') .color('#f00') .size(12) .style({ stroke: '#fff', strokeWidth: 2, }); this.scene.addLayer(pointlayer); ``` ### event 在使用上,瓦片图层绑定事件的操作和普通图层事件保持一致,但是在事件的返回参数中,瓦片图层对分布的数据进行合并操作,以求获取到当前图层的完整数据。 ```javascript layer.on('click', e => {...}); ``` #### 本地运行 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/demo/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/demo.md - Description: 本地运行 --- title: "本地运行" description: "本地运行" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/demo/" --- ### 一、打开L7demo页面 选择一个任意一个你想看的 `demo`。 你可能没有注意到,代码区的上方有一排工具按钮。 ### 二、打开 codesandbox。 点击左侧第三个按钮,你就进入了 `codesandbox`。  你发现你进入了一个在线的代码编辑器,在这里面你可以修改代码,并且能够随时看到效果。 你可能想说我就想本地跑起来,不想在线修改。 当然是是可以的。 ### 三、下载demo源码 1. 在 `codesandbox` 的文件目录工具有下载按钮,参照图中红色部分。 2. 点击下载你可以把这个 `demo` 的源码下载到本地。 ### 四、启动项目 解压项目,进入项目目录。 1. 安装环境依赖 如果不知道 `yarn` 可能需要补充一下前端知识了,如果没有 `yarn` 环境你需要安装一下。 ```bash yarn install ``` 2. 启动项目 ```bash yarn start ``` 浏览器会自动打开 [http://localhost:3000/](http://localhost:3000/),这样 `demo` 就跑起来了。 现在你可以尽情的本地修改代码,添加自己的图层了。 `L7` 所有 `demo` 都可以在 `codesandbox` 打开,你可以下载代码。 #### 网格热力图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/heatmap/grid/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/heatmap/grid.md - Description: 网格热力图 --- title: "网格热力图" description: "网格热力图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/heatmap/grid/" --- 将一组点数据按照等大小的正方形网格进行聚合,一个正方形网格代表网格内所有点的统计值。方格热力图特点以方格网布局。 ### 实现 下面我们来介绍如何绘制一个简单的网格热力图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/heatmap/grid/china/) ```javascript import { Scene, HeatmapLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [107.054293, 35.246265], zoom: 4.056, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv') .then((res) => res.text()) .then((data) => { const layer = new HeatmapLayer({}) .source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'grid', size: 20000, field: 'v', method: 'sum', }, ], }) .shape('square') .style({ coverage: 1, angle: 0, }) .color( 'count', [ '#0B0030', '#100243', '#100243', '#1B048B', '#051FB7', '#0350C1', '#0350C1', '#0072C4', '#0796D3', '#2BA9DF', '#30C7C4', '#6BD5A0', '#A7ECB2', '#D0F4CA', ].reverse(), ); scene.addLayer(layer); }); }); ``` ### source 网格数据只支持点数据作为数据源,数据格式支持 `csv`、`json`、`geojson`。 #### 设置网格聚合参数 布局方法 通过 `source` 的 `transforms` 属性配置。 - type 数据聚合类型 `hexagon`。 - size 网格半径 单位 米。 - field 聚合字段。 - method 聚合方法 `count`,`max`,`min`,`sum`,`mean` 5 个统计维度。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'grid', size: 15000, field: 'v', method: 'sum', }, ], }); ``` ### shape 网格热力图虽然是以标准四边形网格进行数据聚合,但是展示效果上可以设置为各种形状,形状只支持常量。 #### 2d - circle, - triangle - square - heaxgon ```javascript layer.shape('circle'); ``` #### 3d - cylinder - triangleColumn - hexagonColumn - squareColumn, ```javascript layer.shape('cylinder'); ``` ### size ### 2D shape 不需要设置 size 方法 ### 3D 图形 size 表示高度, 支持常量和数据映射 ```javascript layer.size(10); // 常量 layer.size('value', [10, 50]); // 根据value 字段映射大小 layer.size('value', (value) => {}); // 回调函数设置高度 ``` ### color 同 layer color 方法 ### style - coverage 网格覆盖度 0 - 1 - angle 网格旋转角度 0 - 360 - opacity 透明度 0 - 1.0 ```javascript layer.style({ coverage: 0.9, angle: 0, opacity: 1.0, }); ``` #### 弧线图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/line/arc/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/line/arc.md - Description: 弧线图 --- title: "弧线图" description: "弧线图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/line/arc/" --- 有时候为了可视化效果,会选择使用弧线连接地图上的两点。同时也可以使用弧线完成一些有趣的效果。 ### 实现 下面我们来介绍如何使用弧线绘制一个模拟的风场。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/line/animate/animate-line/) ```javascript import { Scene, LineLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [60, 40.7128], zoom: 2, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/7455fead-1dc0-458d-b91a-fb4cf99e701e.txt') .then((res) => res.text()) .then((data) => { const layer = new LineLayer({ blend: 'normal' }) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#6495ED') .animate({ duration: 4, interval: 0.2, trailLength: 0.6, }); scene.addLayer(layer); }); }); ``` ### source 绘制弧线需要同时提供起点和止点的坐标(起止点调换位置,弧线的形状会对称相反,飞线动画的方向也会相反)。 ```javascript const data = [ { lng1: 120, lat1: 30, lng2: 130, lat2: 30, }, ]; layer.source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }); ``` ### shape 为了绘制弧线图,我们需要将 `shape` 的参数设置成 `arc`。 ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) ### style #### segmentNumber arc 图层的弧线默认分段数是 30,然而有有些时候用户并不需要这么多的分段数,适当降低分段数量可以在保证效果的情况下提高性能。 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ segmentNumber: 15, }); ``` #### thetaOffset thetaOffset 参数 表示 arc 弧线的弧度,默认值是 0.314 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ thetaOffset: 0.35, }); ``` [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### linearColor 线图层通过在 style 中设置起始颜色和终点颜色来设置颜色渐变,渐变色的优先级比 color 方法设置的颜色更高 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ sourceColor: '#f00', // 起点颜色 targetColor: '#0f0', // 终点颜色 }); ``` [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) #### dash 线图层通过在 style 中设置线的类型,同时指定虚线部分和实线部分 ```javascript const layer = new LineLayer({}) .source(data) .size(1.5) .shape('line') .color('标准名称', ['#5B8FF9', '#5CCEA1', '#F6BD16']) .active(true) .style({ lineType: 'dash', dashArray: [5, 5], }); scene.addLayer(layer); ``` - lineType 默认为 solid,表示实线,dash 表示虚线 - dashArray[len1: number, len2: number] len1 实线长度 len2 间隔长度 [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) #### 图层初始化 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/monitor/layer_init/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/monitor/layer_init.md - Description: 图层初始化 --- title: "图层初始化" description: "图层初始化" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/monitor/layer_init/" --- 在地图应用中,渲染大数据的地理数据是十分常见的需求,为了保证应用的流畅性,需要追求极致的渲染性能,为此监控引擎渲染内容对于优化性能,建设地图可视化应用性能指标有切实的意义。 ### 实现 下面介绍如何使用 L7 提供的能力简单获取图层的初始化的信息。 ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [60, 40.7128], zoom: 2, }), debug: true, }); scene.on('loaded', () => { const debugService = scene.getDebugService(); const layer = new PointLayer() .source([{ lng: 120, lat: 30 }], { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .shape('circle') .size(10) .color('#f00'); layer.on('inited', () => { console.log(debugService.getLog(layer.id)); }); scene.addLayer(layer); }); ``` #### 地图初始化 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/monitor/map_init/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/monitor/map_init.md - Description: 地图初始化 --- title: "地图初始化" description: "地图初始化" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/monitor/map_init/" --- 在地图应用中,渲染大数据的地理数据是十分常见的需求,为了保证应用的流畅性,需要追求极致的渲染性能,为此监控引擎渲染内容对于优化性能,建设地图可视化应用性能指标有切实的意义。 ### 实现 下面介绍如何使用 L7 提供的能力简单获取地图的初始化的信息。 ```javascript import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [ 60, 40.7128 ], zoom: 2 }), debug: true }); scene.on('loaded', () => { const debugService = scene.getDebugService(); console.log(debugService.getLog('map');) }); ``` #### 3D 柱图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/column/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/column.md - Description: 3D 柱图 --- title: "3D 柱图" description: "3D 柱图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/column/" --- `3D` 柱图是在地理区域上方显示的不同高度的柱体,柱子的高度与其在数据集中的数值会成正比。 ### 实现 下面我们来介绍如何绘制一个常见的 `3D` 柱图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/column/clumn-shape/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 66.02383, center: [ 121.400257, 31.25287 ], zoom: 14.55, rotation: 134.95 }) }); fetch('https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json') .then(res => res.json()) .then(data => { const pointLayer = new PointLayer({}) .source(data, { parser: { type: 'json', x: 'longitude', y: 'latitude' } }) .shape('name', [ 'cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn' ]) .color('name', [ '#739DFF', '#61FCBF', '#FFDE74', '#FF896F' ]); .size('unit_price', h => [ 6, 6, h / 500 ] scene.addLayer(pointLayer); }) ``` ### shape `3D` 柱图 `shape` 方法支持以下参数: - `cylinder` 圆柱体 - `triangleColumn` 三角柱 - `hexagonColumn` 六角柱 - `squareColumn` 四角柱 ### size `3D` 柱图的 `size` 支持设置三个维度 `[w, l, z]`: - `w` 宽 - `l` 长 - `z` 高度 1. `size` 设置常量 ```js layer.size([2, 2, 3]); ``` 2. `size` 设置回调函数 ```js layer.size('unit_price', (h) => { return [6, 6, h / 500]; }); ``` ### animate `3D` 柱图支持生长动画,通过 `animate` 方法进行设置,具体使用可以查看[详细文档](/zh/api/point_layer/animate#生长动画) ### style `3D` 柱图有特殊的 `style` 属性,具体使用可以查找[详细文档](/zh/api/point_layer/style#3d-column) #### 3D 填充图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/polygon/extrude/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/polygon/extrude.md - Description: 3D 填充图 --- title: "3D 填充图" description: "3D 填充图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/polygon/extrude/" --- 几何体图层在地图上除了平面的填充图,还可以是有高度的几何体块。 ### 实现 下面我们来介绍如何绘制一个简单的 `3D` 填充图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/polygon/3d/polygon-stylemap/) ```javascript import { Scene, PolygonLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', pitch: 50, center: [ 118.8, 32.056 ], zoom: 10 }) }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json') .then(res => res.json()) .then(data => { const filllayer = new PolygonLayer({ name: 'fill', zIndex: 3 }) .source(data) .shape('extrude') .color('unit_price', [ '#87CEFA', '#00BFFF', '#7FFFAA', '#00FF7F', '#32CD32', '#F0E68C', '#FFD700', '#FF7F50', '#FF6347', '#FF0000' ]) .size('unit_price', unit_price => unit_price * 50) .style({ opacity:{ field:'unit_price', value: [ 0, 1 ] } pickLight: true }) scene.addLayer(filllayer); }); }); ``` ### source 几何体图层推荐使用标准的 `GeoJSON` 数据。 ### shape 3D Polygon 将多边形沿 Z 轴向上拉伸 - extrude 常量不支持数据映射 ```javascript layer.shape('extrude'); ``` ### size size 代表拉伸的高度,支持数据映射 ```javascript layer.size(10); // 高度设置成常量 layer.size('floor', [0, 2000]); // 根据floor字段进行数据映射默认为线 layer.size('floor', (floor) => { // 通过回调函数设置size return floor * 2; }); ``` ### style - `pickLight` 设置 3D 填充图的拾取高亮色是否计算光照。 `pickLight` 默认为 `false` 表示对拾取的颜色不进行光照计算,开启后会增加部分额外的计算。 ```javascript style({ pickLight: true, // 默认为 false }); ``` - `heightFixed` 设置 `3D` 填充图的高度时候固定。 默认 `3D` 填充图的高度会和 `zoom` 的层级相关,并以此来保持图形高度的像素长度不变,而在某些情况下我们需要保持图形的实际高度不变而不是像素高度不变。 ```javascript style({ heightfixed: true, // 默认为 false }); ``` 🌟 在 v2.7.6 版本开始支持。 [在线案例](/zh/examples/polygon/extrusion/polygon/) - `raisingHeight` 设置 `3D` 填充图的抬升高度。 🌟 设置抬升高度的前提是 `heightfixed` 为 `true`。 🌟 在 v2.8.17 版本开始支持。 [在线案例](/zh/examples/polygon/3d/floatmap/) - `mapTexture` 设置 `3D` 填充图的顶面纹理。 🌟 在设置 `mapTexture` 的时候允许用户配置侧面的渐变色。 🌟 在 v2.8.17 版本开始支持。 ```javascript const provincelayer = new PolygonLayer({}) .source(data) .size(150000) .shape('extrude') .color('#0DCCFF') .style({ heightfixed: true, pickLight: true, raisingHeight: 200000, mapTexture: 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*0tmIRJG9cQQAAAAAAAAAAAAAARQnAQ', sourceColor: '#333', targetColor: '#fff', }); ``` - `topsurface`: `boolean` 控制顶面的显隐,默认为 `true`。 - `sidesurface`: `boolean` 控制侧面的显隐,默认为 `true`。 [在线案例](/zh/examples/polygon/3d/polygon/) #### 快速上手 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/quickstart/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/quickstart.md - Description: 快速上手 --- title: "快速上手" description: "快速上手" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/quickstart/" --- `L7` 可以通过在线 `CDN` 以及 `NPM` 包等形式快速接入。通过 `L7` 提供的能力,我们可以快速完成地图可视化的绘制。 ## 安装引入 ### 通过 npm 引入 ```javascript // 安装L7 依赖 npm install --save @antv/l7 // 安装第三方底图依赖 npm install --save @antv/l7-maps ``` ### 通过 CDN 引入 ```html ``` CDN 引用 在使用时通过 L7 命名空间获取所有对象并初始化,如 L7.scene、L7.GaodeMap ```html ``` ```javascript import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new L7.Scene({ id: 'map', map: new L7.GaodeMap({ style: 'dark', center: [110.770672, 34.159869], pitch: 45, }), }); ``` ## 基础教程 ### 地图组件使用 1. 初始化地图首先需要在页面中新增一个Dom 用于地图初始化。 ```html ``` 2. 初始化高德地图 ```javascript import { GaodeMap } from '@antv/l7-maps'; // 同样你也可以初始化一个 Mapbox 地图 const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 35.210526315789465, style: 'dark', center: [104.288144, 31.239692], zoom: 4.4, }), }); ``` 🌟 此时在页面上就会出现可交互的地图内容。 ### 绘制填充图 地图初始化完成之后我们,那我们就可以往地图添加可视化数据了,这里我们以中国行政区区数据为例,如何可视化面数据。 数据源: 中国各省 [GeoJSON](https://gw.alipayobjects.com/os/bmw-prod/d6da7ac1-8b4f-4a55-93ea-e81aa08f0cf3.json) 数据。 1. 我们使用面图层来绘制行政区划数据,得到覆盖在地图表面的几何平面。 ```javascript import { PolygonLayer } from '@antv/l7'; const chinaPolygonLayer = new PolygonLayer({}) .source(data) .color('name', [ 'rgb(239,243,255)', 'rgb(189,215,231)', 'rgb(107,174,214)', 'rgb(49,130,189)', 'rgb(8,81,156)', ]); ``` 2. 图层创建完成之后我们需要将它添加到 `Scene` 中进行显示。 ```javascript scene.addLayer(chinaPolygonLayer); ```  3. 简单的填充可视化还是不够直观,我们可以使用 `LineLayer` 和 `PointLayer` 增加行政区划描边和行政区划文字标注。  4. 添边界和文本标注之后可视化效果更加清晰。 [查看完整代码](https://codesandbox.io/s/l7-tianchongtujiaocheng-275ix?file=/index.js) ### 交互式填充图 单纯的数据展现出来,并不能满足我的需求,我们可能需要查看每个区块的相关信息,或者添加一些高亮效果。 #### 默认高亮 `L7` 图层添加默认的高亮效果,默认的高亮效果可以改变颜色。 ```javascript chinaPolygonLayer.active(true); // 开启默认高亮效果 chinaPolygonLayer.active({ color: red }); // 开启并设置高亮颜色为红色 ``` | **** | **** | | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | 默认蓝色高亮效果 | 更改高亮颜色 | #### 自定义高亮效果 默认的高亮效果只能改变颜色,可能并不能满足我的需求,我们可能需要白色的描边,这能够实现吗,答案肯定是可以的。 1. 添加一个新的图层的作为高亮图层, 数据我们设置成空数据,形状设置成 `line` ```javascript const hightLayer = new LineLayer({ zIndex: 4, // 设置显示层级 name: 'hightlight', }) .source({ type: 'FeatureCollection', features: [], }) .shape('line') .size(2) .color('red'); scene.addLayer(hightLayer); ``` 2. 这样我们就可以监听需要高亮图层的鼠标事件,获取当前选中的数据,然后更新 `hightLayer` 既可实现描边高亮效果。 ```javascript chinaPolygonLayer.on('click', (feature) => { hightLayer.setData({ type: 'FeatureCollection', features: [feature.feature], }); }); ```  3. 为图层添加点击高亮红色描边效果 到这里我们就学会了如何自定义高亮效果,这里提个小问题“如何实现双描边的高亮效果?” [查看示例](https://codesandbox.io/s/zidingyigaoliang-7vkso?file=/index.js) #### 添加信息 Popup 信息窗 鼠标交互时,我们除了高亮显示划过的区域我们还需要信息区域相关的信息,这里 `L7` 提供了 `Popup` 组件用于在地图显示相关信息。 引入对象 ```javascript import { Popup } from '@antv/l7'; ``` 我们可以通过对 Layer 监听鼠标事件,决定何时显示Popup, ```javascript layer.on('mousemove', (e) => { const popup = new Popup({ offsets: [0, 0], closeButton: false, }) .setLnglat(e.lngLat) .setHTML( `地区: ${e.feature.properties.name}确诊数: ${e.feature.properties.case}`, ); scene.addPopup(popup); }); ```  [查看示例](https://codesandbox.io/s/popup-x3j00?file=/index.js) ### 添加图例 上面我们已经学会了如何可视化数据,在地图我们将不同的区域可视为不同颜色,但是如何读懂不同的颜色表达的什么含义,我们需要添加一个图例。 `L7` 目前没有默认的图例组件,需要自己创建图例,这里我们介绍通过 `L7 Control` 基类创建图例组件,当然你也可以实现一个独立的图例 `DOM` 组件。 `L7` 提供了默认的 `Zoom`,`Scale`,`Logo` 等组件这些组件都基于同一个基类 `Control` 组件,今天我们基于 `Control` 实现自定义图例组件。 1. 引入 `Control` 基类 ```javascript import { Control } from '@antv/l7'; ``` 2. 初始化基类 ```javascript const legend = new Control({ position: 'bottomright', }); ``` 3. 设置 `Control` 展示内容 通过扩展 `Control` 的 `onAdd` 方法我们自由定制 `Control` 需要展示内容和交互。 ```javascript legend.onAdd = function () { var el = document.createElement('div'); el.className = 'infolegend legend'; var grades = [0, 10, 20, 50, 100, 200, 500]; for (var i = 0; i < grades.length; i++) { el.innerHTML += ' ' + grades[i] + (grades[i + 1] ? '–' + grades[i + 1] + '' : '+'); } return el; }; ``` 4. 添加到地图 ```javascript scene.addControl(legend); ```  [查看示例](https://codesandbox.io/s/tuli-keov0?file=/index.js) 这里我们介绍了,如何通过自己定义 `Control` 的方式实现图例,通过自定义 `Control` 我们很多地图组件,如全屏组件,定位组件,很多业务上需要的组件,有幸运的同学们可以动手尝试一下了。 ### 时序变化图 上面我们可视化的是一个静态数据,但是很多时候我们的数据是随时间变化的,如何进行时序数据的可视化,这里我们介绍两种时序数据可视化方法。 #### 准备数据 地理数据:[美国各州行政区划数据](https://gw.alipayobjects.com/os/basement_prod/d36ad90e-3902-4742-b8a2-d93f7e5dafa2.json) 属性数据:[0908-1008近30天的美国各州新冠确诊数据](https://gw.alipayobjects.com/os/bmw-prod/bed5e504-04d5-4d96-a335-163e038dc65a.csv)。 #### 更新数据 随着时间的变化,数据肯定发生变化,因此最简单的方式我每个时间更新一下数据即可. ```javascript chinaPolygonLayer.setData(newData); ``` [完整示例](https://codesandbox.io/s/shujugengxin-kgwy0?file=/index.js) #### 更新颜色 时序数据的更新很大一部分场景是属性数据的更新,比如各省不同年份的 `GDP` 数据,空间数据本身没有发生变化(没有增加或者减少也没有更新边界)这种情况对面图层来说可能只需要根据新的数据更新一下就可以实现。当然通过 `setData` 也可以实现。`L7` 内部实现机制来看 更新 `color` 的效率要比 `setData` 效率高的多。 通过更新颜色映射字段,实现数据显示的更新。 ```javascript const setColor = (d) => { return d > 100000 ? color[7] : d > 80000 ? color[6] : d > 40000 ? color[5] : d > 20000 ? color[4] : d > 10000 ? color[3] : d > 5000 ? color[2] : d > 1000 ? color[1] : color[0]; }; chinaPolygonLayer.color('2020-09-01', setColor); chinaPolygonLayer.color('2020-09-02', setColor); ``` 注意更新颜色生效,需要调用 `Scene.render();`。 [查看示例](https://codesandbox.io/s/shujugengxin-forked-0zul8?file=/index.js) ### 添加地图标注 `L7` 基础 `WebGL` 实现绘制简单的点、线、面,比较简单,如果要实现比较复杂的地图标注就比较困难,为了解决这个问题 `L7` 添加了 `Marker` 组件,你可以基于 `DOM` 实现各种复杂的标注。 ```javascript import { Marker } from '@antv/l7'; const el = document.createElement('label'); el.className = 'labelclass'; el.textContent = nodes[i].v + '℃'; el.style.background = 'red'; el.style.borderColor = '#fff; const marker = new Marker({ element: el}) .setLnglat({ lng: 112, lat: 30}); scene.addMarker(marker); ```  [查看完整代码](https://codesandbox.io/s/nifty-yonath-k6zor?file=/index.html) ### 添加地图组件 除了地图可视化层之外我们可能需要添加辅助性的地图工具 比如放大缩小,比例尺,图层列表等组件。 ```javascript import { Scale, Zoom } from '@antv/l7'; const zoomControl = new Zoom({ position: 'topright' }); const scaleControl = new Scale({ position: 'bottomright' }); // 添加到地图场景 scene.addControl(zoomControl); scene.addControl(scaleControl); ``` #### 自定义组件 上面介绍的图例就是一个自定义组件,同样我们可以任意组件内容,也可以为组件添加地图交互。 更多使用方式我们参考 `L7` 提供默认组件的[源码](https://github.com/antvis/L7/tree/master/packages/component/src/control) ## 不同项目使用模板 不同项目模板在 `CodeSandbox` 你可以预览,也可以下载到本地。 ### React [地址](https://codesandbox.io/s/l720react-jfwyz) ### Vue [地址](https://codesandbox.io/s/l720vue-uef1x) ### Angular [地址](https://codesandbox.io/s/angulartest-chpff) ### HTML CDN [地址](https://codesandbox.io/s/l7cdndemo-gfg9m) #### 栅格瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/tile/raster_tile/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/tile/raster_tile.md - Description: 栅格瓦片 --- title: "栅格瓦片" description: "栅格瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/tile/raster_tile/" --- 栅格瓦片图层包括图片栅格和数据栅格,其中图片栅格通常加载 `png/jpg` 图片,数据栅格则加载 `tiff/lerc` 等栅格数据文件. ### 绘制图片栅格 - TMS ```javascript // 图片瓦片图层 - 卫星图 const layer = new RasterLayer().source( 'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', updateStrategy: 'overlap', }, }, ); ``` ### 绘制图片栅格 - WMS ```javascript // 绘制 WMS 格式瓦片 const url = 'https://pnr.sz.gov.cn/d-suplicmap/dynamap_1/rest/services/LAND_CERTAIN/MapServer/export?F=image&FORMAT=PNG32&TRANSPARENT=true&layers=show:1&SIZE=256,256&BBOX={bbox}&BBOXSR=4326&IMAGESR=3857&DPI=90'; const layer = new RasterLayer().source(url, { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 1, }, }); ``` ### 绘制图片栅格 - WMTS ```javascript // 绘制 WMTS 格式瓦片 const url1 = 'https://t0.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&'; const layer1 = new RasterLayer().source(url1, { parser: { type: 'rasterTile', tileSize: 256, wmtsOptions: { layer: 'img', tileMatrixset: 'w', format: 'tiles', }, }, }); ``` ### 绘制数据栅格 - arraybuffer ```javascript const tileSource = new Source( 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/l7/tiff_jx/{z}/{x}/{y}.tiff', { parser: { type: 'rasterTile', dataType: 'arraybuffer', tileSize: 256, maxZoom: 13.1, format: async (data) => { const tiff = await GeoTIFF.fromArrayBuffer(data); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { rasterData: values[0], width, height }; }, }, }, ); layer.source(tileSource).style({ domain: [0.001, 11.001], clampLow: false, rampColors: { colors: colorList, positions, }, }); ``` ### 绘制数据栅格 - rgb ```javascript const url = 'https://gw.alipayobjects.com/zos/raptor/1667832825992/LC08_3857_clip_2.tif'; const tiffdata = await getTiffData(url); const layer = new RasterLayer({ zIndex: 10 }).source( [ { data: tiffdata, bands: [7, 6, 5].map((v) => v - 1), }, ], { parser: { type: 'rasterRgb', format: async (data, bands) => { const tiff = await GeoTIFF.fromArrayBuffer(data); const image1 = await tiff.getImage(); const value = await image1.readRasters(); return bands.map((band) => { return { rasterData: value[band], width: value.width, height: value.height, }; }); }, operation: 'rgb', extent: [130.39565357746957, 46.905730725742366, 130.73364094187343, 47.10217234153133], }, }, ); ``` #### 数据 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/data/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/data.md - Description: 数据 --- title: "数据" description: "数据" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/data/" --- ## 数据 目前L7支持的数据格式有 `GeoJSON`,`CSV`,`JSON`,`Image`。 - `GeoJSON` 支持点、线、面等所有的标准空间数据格式。 - `CSV` 支持点、线段、弧线等数据类型。 - `JSON` 支持简单的点、线,面数据类型,不支持多点,多线的,多面数据格式。 ### GeoJSON `GeoJSON` 是一种对各种地理数据结构进行编码的格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。 ```json { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [ [110.478515625, 32.76880048488168], [117.68554687499999, 32.76880048488168], [117.68554687499999, 37.64903402157866] ] ] } } ] } ``` ## 地理统计分析工具 [turfjs](http://turfjs.org/): 地理数据计算,处理,统计,分析的Javascript 库 ## 在线工具 [http://geojson.io/](http://geojson.io/) 可以在线查看,绘制,修改GeoJSON数据 [https://mapshaper.org/](https://mapshaper.org/) 可以查看较大的geojson,还能够简化GeoJSON数据 ## 数据资源 #### 全国行政区划GeoJON 支持省市县维度 [geojson, svg下载](http://datav.aliyun.com/tools/atlas/#&lat=33.50475906922609&lng=104.32617187499999&zoom=4) #### HighCharts 全球行政区划数据集 [https://img.hcharts.cn/mapdata/](https://img.hcharts.cn/mapdata/) #### 蜂窝热力图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/heatmap/hexagon/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/heatmap/hexagon.md - Description: 蜂窝热力图 --- title: "蜂窝热力图" description: "蜂窝热力图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/heatmap/hexagon/" --- 将一组点数据按照等大小的六边形网格进行聚合,一个六边形网格代表网格内所有点的统计值。蜂窝热力图特点以六边形热力图网格布局。 ### 实现 下面我们来介绍如何绘制一个简单的蜂窝热力图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/heatmap/hexagon/china/) ```javascript import { Scene, HeatmapLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', pitch: 43, center: [120.13383079335335, 29.651873105004427], zoom: 7.068989519212174, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/a1a8158d-6fe3-424b-8e50-694ccf61c4d7.csv') .then((res) => res.text()) .then((data) => { const layer = new HeatmapLayer({}) .source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'hexagon', size: 2500, field: 'v', method: 'sum', }, ], }) .size('sum', (sum) => { return sum * 200; }) .shape('hexagonColumn') .style({ coverage: 0.8, angle: 0, }) .color('sum', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#C3F9CC', '#DEFAC0', '#ECFFB1', ]); scene.addLayer(layer); }); }); ``` ### source 网格数据只支持点数据作为数据源,数据格式支持 `csv`、`json`、`geojson`。 #### 设置网格聚合参数 布局方法 通过 `source` 的 `transforms` 属性配置。 - type 数据聚合类型 `hexagon`。 - size 网格半径 单位 米。 - field 聚合字段。 - method 聚合方法 `count`,`max`,`min`,`sum`,`mean` 5 个统计维度。 ```javascript layer.source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'hexagon', size: 15000, field: 'v', method: 'sum', }, ], }); ``` ### shape 网格热力图虽然是以标准四边形网格进行数据聚合,但是展示效果上可以设置为其形状,形状只支持常量 #### 2d - circle, - triangle - square - heaxgon ```javascript layer.shape('circle'); ``` #### 3d - cylinder - triangleColumn - hexagonColumn - squareColumn, ```javascript layer.shape('cylinder'); ``` ### size ### 2D shape 不需要设置 size 方法 ### 3D 图形 size 表示高度, 支持常量和数据映射 ```javascript layer.size(10); // 常量 layer.size('value', [10, 50]); // 根据value 字段映射大小 layer.size('value', (value) => {}); // 回调函数设置高度 ``` ### style - coverage 网格覆盖度 0 - 1 - angle 网格旋转角度 0 - 360 - opacity 透明度 0 - 1.0 ```javascript layer.style({ coverage: 0.9, angle: 0, opacity: 1.0, }); ``` #### 3D 弧线图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/line/arc3d/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/line/arc3d.md - Description: 3D 弧线图 --- title: "3D 弧线图" description: "3D 弧线图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/line/arc3d/" --- 除了 2D 的弧线,我们还指出 3D 的弧线,在使用上只要改变 `shape` 的参数即可。 ### 实现 下面我们来介绍如何绘制一个简单的 `3D` 弧线图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/line/arc/trip-arc/) ```javascript import { LineLayer } from '@antv/l7'; 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, }); ``` ### source 绘制弧线需要同时提供起点和止点的坐标(起止点调换位置,弧线的形状会对称相反,飞线动画的方向也会相反)。 ```javascript const data = [ { lng1: 120, lat1: 30, lng2: 130, lat2: 30, }, ]; layer.source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }); ``` ### shape 为了绘制弧线图,我们需要将 `shape` 的参数设置成 `arc3d`。 ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) ### style #### linearColor 线图层通过在 style 中设置起始颜色和终点颜色来设置颜色渐变,渐变色的优先级比 color 方法设置的颜色更高 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ sourceColor: '#f00', // 起点颜色 targetColor: '#0f0', // 终点颜色 }); ``` [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) #### dash 线图层通过在 style 中设置线的类型,同时指定虚线部分和实线部分 ```javascript const layer = new LineLayer({}) .source(data) .size(1.5) .shape('line') .color('标准名称', ['#5B8FF9', '#5CCEA1', '#F6BD16']) .active(true) .style({ lineType: 'dash', dashArray: [5, 5], }); scene.addLayer(layer); ``` - lineType 默认为 solid,表示实线,dash 表示虚线 - dashArray[len1: number, len2: number] len1 实线长度 len2 间隔长度 [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) #### 使用无底图模式 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/blankmap/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/blankmap.md - Description: 使用无底图模式 --- title: "使用无底图模式" description: "使用无底图模式" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/blankmap/" --- 很多情况下我们只是做些简单的地理可视化,不需要加载地图,本教程就是告诉大家如果在L7中使用无底图模式。 - `L7` 在地图样式层面增加了无底图样式 `blank` 无底图模式。 - 不需要使用 `mapbox token` ,也不需要注册 `mapbox` 账户。 ```javascript const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'blank', center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, }), }); ``` 🌟 如果你只是需要做个中国地图,世界地图这样填充图,建议你采用这样的模式。 #### Leaflet 地图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/leaflet/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/leaflet.md - Description: Leaflet 地图 --- title: "Leaflet 地图" description: "Leaflet 地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/leaflet/" --- `L7` 通过提供插件的形式实现了对 `Leaflet` 的支持,实现 `Leaflet` 地图和 `L7` 可视化图层的融合。 ### L7-Leaflet - `L7-Leaflet` 是对外开源的插件 [github 地址](https://github.com/antvis/L7-Leaflet) ### 安装 #### npm ```bash npm install @antv/l7-leaflet ``` #### cdn ```javascript ``` ### 使用 #### L7 plugin for Lealfet use in Leaflet ```js import * as L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { LineLayer } from '@antv/l7'; import { L7Layer } from '@antv/l7-leaflet'; import React, { useEffect } from 'react'; export default () => { useEffect(() => { const map = L.map('map', { minZoom: 1, }).setView([30, 112], 3); const mapType = 'vec'; L.tileLayer( 'https://t{s}.tianditu.gov.cn/' + mapType + '_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + mapType + '&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=b72aa81ac2b3cae941d1eb213499e15e', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], attribution: '© 天地图 GS(2022)3124号 - 甲测资字1100471', }, ).addTo(map); const mapLabelType = 'cva'; L.tileLayer( 'https://t{s}.tianditu.gov.cn/' + mapLabelType + '_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + mapLabelType + '&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=b72aa81ac2b3cae941d1eb213499e15e', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], }, ).addTo(map); L.marker([30, 112]) .addTo(map) .setIcon( new L.Icon({ iconUrl: 'https://gw.alipayobjects.com/mdn/rms_5e897d/afts/img/A*6ONoRKNECC0AAAAAAAAAAAAAARQnAQ', iconSize: [16, 16], }), ) .bindPopup('A pretty CSS3 popup. Easily customizable.') .openPopup(); const l7layer = new L7Layer().addTo(map); const scene = l7layer.getScene(); 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); }); }, []); return ( ); }; ``` #### Leafet BaseMap for L7 use in L7 ```js import * as L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { LineLayer } from '@antv/l7'; import { L7Layer } from '@antv/l7-leaflet'; import React, { useEffect } from 'react'; export default () => { useEffect(() => { const map = L.map('map', { minZoom: 1, }).setView([30, 112], 3); const mapType = 'vec'; L.tileLayer( 'https://t{s}.tianditu.gov.cn/' + mapType + '_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + mapType + '&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=b72aa81ac2b3cae941d1eb213499e15e', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], attribution: '© 天地图 GS(2022)3124号 - 甲测资字1100471', }, ).addTo(map); const mapLabelType = 'cva'; L.tileLayer( 'https://t{s}.tianditu.gov.cn/' + mapLabelType + '_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + mapLabelType + '&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=b72aa81ac2b3cae941d1eb213499e15e', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], }, ).addTo(map); L.marker([30, 112]) .addTo(map) .setIcon( new L.Icon({ iconUrl: 'https://gw.alipayobjects.com/mdn/rms_5e897d/afts/img/A*6ONoRKNECC0AAAAAAAAAAAAAARQnAQ', iconSize: [16, 16], }), ) .bindPopup('A pretty CSS3 popup. Easily customizable.') .openPopup(); const l7layer = new L7Layer().addTo(map); const scene = l7layer.getScene(); 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); }); }, []); return ( ); }; ``` #### 天地图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/tianditu/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/tianditu.md - Description: 天地图 --- title: "天地图" description: "天地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/tianditu/" --- `L7` 支持通过瓦片图层的方式来加载天地图瓦片。 ### 实现 下面我们来介绍如何快速创建天地图地图。 ```js import { Scene, RasterLayer } from '@antv/l7'; import { Map } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Map({ center: [90.268, 40.3628], zoom: 3, }), }); scene.on('loaded', () => { // 底图服务 const baseLayer = new RasterLayer({ zIndex: 1 }).source( 'https://t1.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk=6557fd8a19b09d6e91ae6abf9d13ccbd', { parser: { type: 'rasterTile', tileSize: 256, }, }, ); // 注记服务 const annotionLayer = new RasterLayer({ zIndex: 2 }).source( 'https://t1.tianditu.gov.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}&tk=6557fd8a19b09d6e91ae6abf9d13ccbd', { parser: { type: 'rasterTile', tileSize: 256, }, }, ); scene.addLayer(baseLayer); scene.addLayer(annotionLayer); }); ``` #### 聚合图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/cluster/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/cluster.md - Description: 聚合图 --- title: "聚合图" description: "聚合图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/cluster/" --- 聚合图通常用来描述数据在地理上表现的聚合情况,类似热力图,可以用来表示数据点位的集中。 🌟 目前 `L7` 只有点数据支持聚合图,聚类方法主要从数据层聚合数据,在 `Source` 方法配置 `cluster` 参数。 ### 实现 下面我们来介绍如何绘制一个常见的聚合图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/cluster/cluster/) ```js import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [120.19382669582967, 30.258134], style: 'dark', zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data, { cluster: true }) .shape('circle') .scale('point_count', { type: 'quantile', }) .size('point_count', [5, 10, 15, 20, 25]) .active(true) .color('yellow') .style({ opacity: 0.5, strokeWidth: 1, }); scene.addLayer(pointLayer); }); }); ``` ### source 聚合图在接受普通的点数据之后还需要配置聚合参数。 ```js const source = new Source(data, { cluster: true, clusterOption: { radius: 40, minZoom: 0, maxZoom: 16, }, }); ``` - `cluster: boolean` 表示是否对数据进行聚合操作,目前只有点图层支持,默认值为 `false`。 - `clusterOption: IClusterOption` 具体的聚合参数 - `radius: number` 聚合半径,默认值为 `40`。 - `minZoom: number` 最小聚合缩放等级,默认值为 `0`。 - `maxZoom: number` 最大聚合缩放等级,默认值为 `16`。 ```js interface IClusterOption { radius, minZoom maxZoom } ``` [在线案例](/zh/examples/point/cluster/cluster/) ### shape 聚合图使用通用的聚合样式,`shape` 只要使用点图层类型的 `shape` 即可。 ### FAQ `PointLayer` 的聚合图采用 `WebGL` 绘制,不支持自定义具体聚合样式,如果有自定义的需求可以使用 `MarkerLayer` 的聚合功能,你可以通过 `DOM` 完全自定义样式。 [MarkerLayer 聚合](/zh/api/component/marker_layer) #### 散点图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/scatter/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/scatter.md - Description: 散点图 --- title: "散点图" description: "散点图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/scatter/" --- 散点图在地理区域上放置相等大小的圆点,用来表示地域上的空间布局或数据分布。 ### 实现 下面我们来介绍如何绘制一个常见的散点图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/scatter/scatter/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [-121.24357, 37.58264], zoom: 6.45, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/6c4bb5f2-850b-419d-afc4-e46032fc9f94.csv') .then((res) => res.text()) .then((data) => { const pointLayer = new PointLayer({}) .source(data, { parser: { type: 'csv', x: 'Longitude', y: 'Latitude', }, }) .shape('circle') .size(4) .color('Magnitude', [ '#0A3663', '#1558AC', '#3771D9', '#4D89E5', '#64A5D3', '#72BED6', '#83CED6', '#A6E1E0', '#B8EFE2', '#D7F9F0', ]); scene.addLayer(pointLayer); }); }); ``` ### shape 散点图 `shape` 一般设置成常量,通常是 `2D` 的图表。 - circle - square - hexagon - triangle - pentagon - octogon - hexagram - rhombus - vesica #### water fill - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/polygon/water/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/polygon/water.md - Description: water fill --- title: "water fill" description: "water fill" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/polygon/water/" --- 几何体图层支持特殊的表现形式,水面图层。 ### 实现 下面我们来介绍如何绘制水面。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/polygon/fill/ocean/) 🌟 从 v2.8.1 版本开始支持简单水面。 🌟 从 v2.8.4 版本开始支持拟真水面。 ### 拟真水面 ### source 几何体图层推荐使用标准的 `GeoJSON` 数据。 ### shape 我们需要设置 `shape` 为 `ocean`。 ### animate 我们需要显示的设置 `animate` 为 `true`。 ```javascript layer.aniamte(true); ``` ### style - `watercolor` 浅水区域的颜色 默认为 '#6D99A8'。 - `watercolor2` 深水区域的颜色 默认为 '#0F121C'。 [在线案例](/zh/examples/polygon/fill/ocean/) ### 简单水面 ### source 几何体图层推荐使用标准的 `GeoJSON` 数据。 ### shape 我们需要设置 `shape` 为 `water`。 ### animate 我们需要显示的设置 `animate` 为 `true`。 ```javascript layer.aniamte(true); ``` ### style - `speed` 我们可以通过 `speed` 来控制水面的流速度。 ```javascript style({ speed: 0.5, }); ``` - `waterTexture` 我们可以通过设置该属性来替换水面的纹理。 默认值是 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*EojwT4VzSiYAAAAAAAAAAAAAARQnAQ' [在线案例](/zh/examples/polygon/fill/water/) #### Scale 度量 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/scale/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/scale.md - Description: Scale 度量 --- title: "Scale 度量" description: "Scale 度量" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/scale/" --- ## Scale 简介 Scale 度量是用于将地图数据值(数字、日期、类别等数据)转成视觉变量(颜色、大小、形状)。Scale 是数据可视化的基本元素,因为它们决定了数据视觉编码的方式。L7 目前支持连续、离散、枚举类型等常用的 Scale。  ## Scale 中的两个重要概念: Range 和 Domain Domain: 地图数据值的定义区间 Range:视觉值的区间定义 不同 Scale 的差异在于 Domain-> Range 的转换方法不同 | 数据类 | 度量类型 | | --------- | ------------------------------------- | | 连续 | linear、log、pow | | 连续分类 | quantize quantile,threshold,diverging | | 分类 枚举 | cat | ## L7 Scale 在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: 查看用户是否设置了 Scale,如果没有: 判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: 认为是常量为固定值 如果是数字则为 'linear'; 如果是字符串类型 'cat'; ## Cat 枚举 Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。在 L7 如果判断字段的值为字符串,将认为是 Cat 类型并自动获取类型的唯一值,设置为 domain 。这样三种作物就会被一一映射成对应的颜色。 ```tsx const data = [ { type:'A', x: 110, y:30 }, { type:'B', x: 110, y:32 }, { type:'C', x: 110, y:31 } ,{ type:'D', x: 111, y:33 }, ,{ type:'E', x: 112, y:30 } ,{ type:'F', x: 110, y:30 } ] layer.color('type',['red','white','blue','yellow']) ``` 如上面的代码所示,图层没有设置 Scale, L7 根据第一个数据"A"的类型 ,推断为枚举类型。同时取出该字段的去重后的所有值 ['A','B','C','D','E','F'] 设置为 scale 的 domain, 那么 range 就是对应的颜色 ['red','white','blue','yellow']。  如果不设置 domain,L7 内部会自动计算 domain,domain 顺序跟数据顺序相关。如果希望固定domain 可自己设置 domain。domain 数值 和 range数值 一一对应。 ``` layer.scale('type', { type: 'cat', domain: ['B', 'A', 'C', 'D'], }); layer.color('type', ['red', 'white', 'blue', 'yellow']); ```  ## Linear 连续线性 线性是连续数据的映射方法,数据和视觉值是通过线性方法计算的。如数据范围domain [0,1000] 线性映射到 range [red,blue] 渐变色,就是依据线性函完成一一转换。  ```tsx layer.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']); ``` 对于连续型 数据 L7 默认会设置为 linear, domain为数据的min、max值。颜色会根据 range 颜色生成渐变色。linear 默认可不设置 domain 区间 ```ts layer.scale('value', { type: 'linear', domain: [5, 100], // 可定义domain,也可以不设置,自定根据数据计算 }); ``` ## quantize 连续等间距 等间距分类会根据属性值范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量。  等间距分类只与数据 mix、max 有关,如果没有设置 domain,将自动计算数据的 min、max 进行分段,分段个数依据 range 颜色的个数。等间距会出现空类,而且每个分类要素分布不均匀。 ```tsx layer.color('type', ['red', 'white', 'blue', 'yellow']); ``` 你也可以自定义 domain ```ts layer.scale('value', { type: 'quantize', domain: [5, 100], }); layer.color('type', ['red', 'white', 'blue', 'yellow']); ```  ## quantile 连续等分位 等分位要求每个分类区间都含有相等数量的要素。分位数为每个分类分配相等数量数据值,不存在空类,也不存在值过多或过少的类。  等分位与数据的分布相关,需要拿到全量数据才能计算,因此等分位的 scale 不能单独设置 domain,只能自动计算。 ```tsx layer.scale('value', { type: 'quantile', }); layer.color('value', ['red', 'white', 'blue', 'yellow']); ```  ## threshold 自定义分类 自定义分类可以设定任意分类区间映射到对于视觉变量。domain 仍然是连续的,并根据提供的domain 进行分类。range 属性必须有 N+1 个元素,其中 N 是 domain 的个数。 threshold 为自定义分段,在使用时必须为 Scale 设置 domain, domain可以依据需求任意设置。 ```tsx layer .scale('rate', { type: 'threshold', domain: [3, 6, 8, 10], }) .color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']); ```  ## diverging 离散分类 离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。  diverging 如果没有设置 domain 会自动根据数据计算min、middle、max 三个值作为domain。range 至少需要设置三个颜色,形成双极色带。 ```ts layer.scale('rate', { type: 'diverging' domain: [3, 6, 8, 10], // the input domain and output range of a diverging scal }) .color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) ```  #### 矢量瓦片 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/tile/vector_tile/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/tile/vector_tile.md - Description: 矢量瓦片 --- title: "矢量瓦片" description: "矢量瓦片" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/tile/vector_tile/" --- 矢量瓦片通常可以用于大数据量地理数据的渲染,借助瓦片的特性分布请求渲染数据,从而达到减少请求、加载时间的等待,优化使用体验的目的。同时,在不需要全量加载数据的场景下,通过矢量瓦片的形式可以在保证体验的前提下有效减少数据的渲染量,减少渲染压力。 ### 绘制矢量瓦片 - point ```javascript import { PointLayer } from '@antv/l7'; const point = new PointLayer({ featureId: 'COLOR', sourceLayer: 'ecoregions2', }) .source(vectorSource) .shape('circle') .color('red') .size(10); ``` ### 绘制矢量瓦片 - line ```javascript import { LineLayer } from '@antv/l7'; const line = new LineLayer({ featureId: 'COLOR', sourceLayer: 'ecoregions2', }) .source(vectorSource) .color('COLOR') .size(2); ``` ### 绘制矢量瓦片 - polygon ```javascript // 矢量瓦片图层 import { PolygonLayer } from '@antv/l7'; const polygon = new PolygonLayer({ featureId: 'COLOR', sourceLayer: 'ecoregions2', }) .source(source) .color('red'); ``` ### 绘制矢量瓦片 - 掩模图层 矢量掩模图层一般配合栅格图层使用,对栅格图层进行掩模处理。 ```js import { MaskLayer } from '@antv/l7'; const mask = new MaskLayer({sourceLayer: 'ecoregions2' }) .source( 'https://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf' { parser: { type: 'mvt', maxZoom: 9, extent: [-180, -85.051129, 179, 85.051129], }}); ``` ### 绘制矢量瓦片 - 测试图层 ```js // 测试瓦片图层 const debugerLayer = new TileDebugLayer(); ``` #### 大圆航线 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/line/greatcircle/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/line/greatcircle.md - Description: 大圆航线 --- title: "大圆航线" description: "大圆航线" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/line/greatcircle/" --- 把地球看做一个球体,通过地面上任意两点和地心做一平面,平面与地球表面相交看到的圆周就是大圆。两点之间的大圆劣弧线是两点在地面上的最短距离。沿着这一段大圆弧线航行时的航线称为大圆航线。 ### 实现 下面我们来介绍如何绘制一个简单的大圆弧线。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/line/arc/arc-circle/) ```javascript import { Scene, LineLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', center: [107.77791556935472, 35.443286920228644], zoom: 2.9142882493605033, }), }); scene.on('loaded', () => { 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('greatcircle') .color('#8C1EB2') .style({ opacity: 0.8, }); scene.addLayer(layer); }); }); ``` ### source 绘制弧线需要同时提供起点和止点的坐标(起止点调换位置,弧线的形状会对称相反,飞线动画的方向也会相反)。 ```javascript const data = [ { lng1: 120, lat1: 30, lng2: 130, lat2: 30, }, ]; layer.source(data, { parser: { type: 'json', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }); ``` ### shape 为了绘制大圆弧线图,我们需要将 `shape` 的参数设置成 `greatcircle`。 ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) ### style #### linearColor 线图层通过在 style 中设置起始颜色和终点颜色来设置颜色渐变,渐变色的优先级比 color 方法设置的颜色更高 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ sourceColor: '#f00', // 起点颜色 targetColor: '#0f0', // 终点颜色 }); ``` [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) #### dash 线图层通过在 style 中设置线的类型,同时指定虚线部分和实线部分 ```javascript const layer = new LineLayer({}) .source(data) .size(1.5) .shape('line') .color('标准名称', ['#5B8FF9', '#5CCEA1', '#F6BD16']) .active(true) .style({ lineType: 'dash', dashArray: [5, 5], }); scene.addLayer(layer); ``` - lineType 默认为 solid,表示实线,dash 表示虚线 - dashArray[len1: number, len2: number] len1 实线长度 len2 间隔长度 [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) #### 使用高德插件 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/map/amapplugin/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/map/amapplugin.md - Description: 使用高德插件 --- title: "使用高德插件" description: "使用高德插件" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/map/amapplugin/" --- 我们在使用高德地图作为地图底图的时候,可以借助高德地图提供的插件实现也中需求。 ### AMap.LineSearch - 道路查询 ```javascript const scene = new Scene({ id: 'map', map: new Mapbox({ style: 'blank', center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, }), }); ``` [在线案例](/zh/examples/amap-plugin/bus/busstop/) ### AMap.ToolBar - 地图工具栏 ```javascript scene.on('loaded', () => { window.AMap.plugin([ 'AMap.ToolBar', 'AMap.LineSearch' ], () => { scene.map.addControl(new AMap.ToolBar()); const linesearch = new AMap.LineSearch({ pageIndex: 1, // 页码,默认值为1 pageSize: 1, // 单页显示结果条数,默认值为20,最大值为50 city: '北京', // 限定查询城市,可以是城市名(中文/中文全拼)、城市编码,默认值为『全国』 extensions: 'all' // 是否返回公交线路详细信息,默认值为『base』 }); ``` [在线案例](/zh/examples/amap-plugin/bus/busstop/) ### AMap.TileLayer - 加载使用 `xyz` 地图瓦片 ```javascript scene.on('loaded', () => { var xyzTileLayer = new window.AMap.TileLayer({ getTileUrl: 'https://wprd0{1,2,3,4}.is.autonavi.com/appmaptile?x=[x]&y=[y]&z=[z]&size=1&scl=1&style=8<ype=11', zIndex: 100, }); scene.map.add(xyzTileLayer); }); ``` [在线案例](/zh/examples/amap-plugin/bus/xyztile/) ### AMap.TileLayer.Satellite - 加载使用默认的卫星瓦片 ```javascript scene.on('loaded', () => { scene.map.add(new window.AMap.TileLayer.Satellite()); }); ``` [在线案例](/zh/examples/amap-plugin/bus/satellite/) #### 渲染监控 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/monitor/render/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/monitor/render.md - Description: 渲染监控 --- title: "渲染监控" description: "渲染监控" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/monitor/render/" --- 在地图应用中,渲染大数据的地理数据是十分常见的需求,为了保证应用的流畅性,需要追求极致的渲染性能,为此监控引擎渲染内容对于优化性能,建设地图可视化应用性能指标有切实的意义。 ### 实现 下面介绍如何使用 L7 提供的能力简单获取应用的渲染性能信息。 ```javascript import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [ 60, 40.7128 ], zoom: 2 }), debug: true }); scene.on('loaded', () => { const debugService = scene.getDebugService(); // 开启每帧渲染的监控 debugService.renderDebug(true) debugService.on('renderEnd', renderInfo => { const { renderUid, // 当前帧渲染唯一编号 renderStart, // 当前帧渲染开始时间 renderEnd, // 当前帧渲染结束时间 renderDuration // 当前帧渲染时间 } = renderInfo; ... } setTimeout(() => { debugService.renderDebug(false); debugService.off('renderEnd'); }, 1000); // 监听 1s 内的渲染情况 }); ``` #### 水波图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/wave/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/wave.md - Description: 水波图 --- title: "水波图" description: "水波图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/wave/" --- 平面点图层在开启动画模式的情况下,是一种特殊的图层类型:水波点。图层由一圈圈向外扩散的圆环构成。 ### 实现 根据下面的代码可以实现一个简单的水波点案例。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/scatter/animatepoint/)。 - 具体的使用可以查看[详细文档](/zh/api/point_layer/animate#水波点)。 ```js import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [112, 23.69], zoom: 2.5, }), }); fetch('https://gw.alipayobjects.com/os/basement_prod/9078fd36-ce8d-4ee2-91bc-605db8315fdf.csv') .then((res) => res.text()) .then((data) => { const pointLayer = new PointLayer({}) .source(data, { parser: { type: 'csv', x: 'Longitude', y: 'Latitude', }, }) .shape('circle') .animate(true) .size(40) .color('#ffa842'); scene.addLayer(pointLayer); }); ``` ### shape 为了实现水波点,点图层的 `shape` 参数只要是 `circle`、`triangle`、`square` 等平面图形即可。 ### animate - boolean | animateOption ```javascript .animate(true) .animate({ enable: true }) ``` #### 水波配置项 - `speed` 水波速度 - `rings` 水波环数 ### size 在水波点图层中,由于边缘透明的原因,点的大小看上去要比相同 size 的非水波点要小一些。 #### 简单线图层 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/line/simple/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/line/simple.md - Description: 简单线图层 --- title: "简单线图层" description: "简单线图层" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/line/simple/" --- 简单线图层为用户提供了一种大数据量性能更优的选择,能轻松渲染有几十万个节点的线段,但相应的,对比与普通的线图层,简单线图层也丢失了一些其他能力。 ### 实现 下面我们来介绍如何绘制简单线。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/gallery/animate/grid/) ```javascript import { LineLayer } from '@antv/l7'; const layer = new LineLayer() .source(data) .shape('simple') .size(10) // size 方法不生效 线宽始终为 1px .color('#f00') .style(...) ``` ### shape 为了绘制简单线,我们需要将 `shape` 的参数设置成 `simple`。 #### linearColor 线图层通过在 style 中设置起始颜色和终点颜色来设置颜色渐变,渐变色的优先级比 color 方法设置的颜色更高 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ sourceColor: '#f00', // 起点颜色 targetColor: '#0f0', // 终点颜色 }); ``` [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) 🌟 简单线图层不支持动画和纹理 #### 亮度图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/dot/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/dot.md - Description: 亮度图 --- title: "亮度图" description: "亮度图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/dot/" --- 亮度图又称点密度图,单位面积的内点的个数越多,亮度会越亮,亮度图一般用来表达海量点数据分布情况 ### 实现 下面我们来介绍如何绘制一个简单的亮度图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/gallery/basic/normal/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [121.417463, 31.215175], style: 'dark', zoom: 11, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/BElVQFEFvpAKzddxFZxJ.txt') .then((res) => res.text()) .then((data) => { const pointLayer = new PointLayer({}) .source(data, { parser: { type: 'csv', y: 'lat', x: 'lng', }, }) .size(0.5) .color('#080298'); scene.addLayer(pointLayer); }); }); ``` ### shape 使用亮度图需要将 `shape` 的参数设置为 `dot`,或者不设置 `shape` 函数。 #### 雷达图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/radar/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/radar.md - Description: 雷达图 --- title: "雷达图" description: "雷达图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/radar/" --- 点图层还支持一种特殊的图层类型:雷达图。 ### 实现 下面我们来介绍如何绘制一个常见的雷达图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/scatter/radarpoint/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [120, 30], zoom: 13, }), }); const layer = new PointLayer() .source([{ lng: 120, lat: 30 }], { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .shape('radar') .size(100) .color('#d00') .style({ speed: 5, }) .animate(true); ``` ### source 雷达图接受普通的点数据。 ### shape 雷达图的 `shape` 为固定值 `radar`。 ### animate 雷达图需要将 `animate` 设置为 `true` 才会生效 ```javascript .animate(true) .animate({ enable: true }) ``` ### style 通过 `speed` 设置旋转速度,默认为 `1`,值越大转速越快。 #### 开发者教程 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/develop/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/develop.md - Description: 开发者教程 --- title: "开发者教程" description: "开发者教程" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/develop/" --- 这里的开发者,是指开发 L7 的开发者,为 L7 修复 bug、完善文档、升级功能、新功能开发等能力。 ### Fork 仓库 Fork L7 仓库 到自己的空间。 ### 下载 Fork 后的代码 ```bash git clone https://github.com/antvis/L7 --depth=1 ``` ### 安装依赖 node 版本推荐 v16.20.2 ```bash yarn install ``` ### 启动 Demo 如需功能调试 ```bash yarn run dev ``` 打开 `http://localhost:6006/`: ### 启动 官网 如需更新 API 或者 写文档、demo,使用该命令 ```bash yarn start ``` 打开 `http://localhost:8000/`: ### 运行单测 运行单元测试: ```bash yarn test // 全量跑 yarn test ../tes.spec.ts // 单个文件 ``` ## 提交代码 可以使用 yarn commit 模板化提交: ```bash yarn commit ``` ## 开发任务 L7 Issue 和 Feature 通过开源社区的方式运作管理,可以完全的开放的探索、交流技术方案。开发任务,[认领查看](https://github.com/orgs/antvis/projects/16) 针对 L7 开发者 我们制定了成长计划,帮助大家从初级走向高级 GIS 领域 可视化引擎开发者。如有兴趣可以加 微信 "antv2030",注明 “参与L7研发”,期待你加入,一起学习。 #### 地理围墙 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/line/wall/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/line/wall.md - Description: 地理围墙 --- title: "地理围墙" description: "地理围墙" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/line/wall/" --- 地理围墙在原有线图层的基础上赋予了高度的概念,其他的使用和普通的线图保持一致。 ### 实现 下面我们来介绍如何绘制简单的地理围墙。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/line/wall/hangzhou-wall/) ## 使用 ```javascript import { Scene, LineLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [119.297868, 29.732983], zoom: 7.11, rotation: 1.22, pitch: 45.42056074766357, style: 'dark', }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/93a55259-328e-4e8b-8dc2-35e05844ed31.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({}).source(data).size(40).shape('wall').style({ opacity: 1, sourceColor: '#0DCCFF', targetColor: 'rbga(255,255,255, 0)', }); scene.addLayer(layer); }); }); ``` ### shape 为了绘制地理围墙,我们需要将 `shape` 的参数设置成 `wall`。 ### animate #### 开启关闭动画 ```javascript layer.animate(true); layer.animate(false); ``` #### 设置动画参数 - duration 动画时间 单位(s)秒 - interval 轨迹间隔, 取值区间 0 - 1 - trailLength 轨迹长度 取值区间 0 - 1 ```javascript layer.animate({ duration: 4, interval: 0.2, trailLength: 0.1, }); ``` ##### 参数动画介绍 L7 目前动画参数为相对单位,我们默认一条线段的长度为 1  如果 interval = 0.2,则一条轨迹将会分成 5 段,如果 interval = 0.5 则为两段。 [在线案例](/zh/examples/line/animate/plane-animate2/) ### style #### linearColor 线图层通过在 style 中设置起始颜色和终点颜色来设置颜色渐变,渐变色的优先级比 color 方法设置的颜色更高 ```javascript const layer = new LineLayer({}) .source(data, { parser: { type: 'csv', x: 'lng1', y: 'lat1', x1: 'lng2', y1: 'lat2', }, }) .size(1) .shape('arc') .color('#8C1EB2') .style({ sourceColor: '#f00', // 起点颜色 targetColor: '#0f0', // 终点颜色 }); ``` [在线案例](/zh/examples/line/arc/trip-arc-dark-linear/) 🌟 目前渐变色的方向为垂直向上 线图层支持纹理贴图和多种表现形式,通过 `scene.addImage` 方法添加到全局的资源,使用 `texture` 方法指定贴图。 ```javascript scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); const layer = new LineLayer() .source(data) .size(4) .shape('line') .texture('02') .color('#25d8b7') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 }); ``` - lineTexture 指定是否开启纹理贴图能力 - iconStep 指定贴图在线图层上面排布的间隔 [在线案例](/zh/examples/gallery/animate/animate-path-texture/) #### texture advance ✨ animate 当线图层 (`shape` 为 `arc`/`arc3d`) 开启动画模式的时候,纹理在线图层上的分布还会和 `animate` 的参数相关. 线图层上排列的纹理的数量大致为 duration/interval ```javascript .animate({ duration: 1, interval: 0.2, trailLength: 0.1 }); // 此时 纹理贴图数量为 duration / interval = 5 ``` ✨ textureBlend 参数 通过控制 style 方法中的 textureBlend 参数,我们可以控制纹理图层和线图层的混合情况 - normal - replace ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 30, // 设置贴图纹理的间距 textureBlend: 'replace', // 设置纹理混合方式,默认值为 normal,可选值有 normal/replace 两种 }); ``` [在线案例](zh/examples/line/animate#plane_animate2) 🌟 地理围栏支持了新的样式参数 iconStepCount - 纹理间隔只有在开启纹理的时候才会生效 - 纹理间隔支持配置纹理之间的间距 - 纹理间隔需要和纹理间距配合使用 ```javascript .style({ lineTexture: true, // 开启线的贴图功能 iconStep: 40, // 设置贴图纹理的间距 iconStepCount: 4 }) ``` #### heightfixed `wall` 支持了固定高度配置 `heightfixed`。 ```javascript .style({ heightfixed: true // 默认为 false,开启后实际世界高度不变(注意调整尺寸) }) ``` #### 符号图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/symbol/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/symbol.md - Description: 符号图 --- title: "符号图" description: "符号图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/symbol/" --- 点图层支持绘制图标,在地理区域上放置不同图片作为符号,通常表示不同地理要素分布情况 ### 实现 下面我们来介绍如何绘制一个常见的符号地图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/image/image/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [121.434765, 31.256735], zoom: 14.83, }), }); 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', ); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json') .then((res) => res.json()) .then((data) => { const imageLayer = new PointLayer() .source(data, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('name', ['00', '01', '02']) .size(25); scene.addLayer(imageLayer); }); }); ``` ### addImage(field: string, url: string): void 为了使用点图层绘制图标,我们需要事先在 `scene` 全局添加对应的图片资源。之后我们就可以在点图层的 `shape` 方法中指定对应的图片。 ```js scene.addImage( '02', 'https://gw.alipayobjects.com/zos/basement_prod/7aa1f460-9f9f-499f-afdf-13424aa26bbf.svg', ); ``` ### shape 我们需要通过 `shape` 方法指定当前点图层需要加载的图片资源 `ID`,`ID` 是用户使用 `scene.addImage(id, url)` 全局添加图片资源时候的 `ID`,即符号图需要把 `shape` 设置成图片的 `id`。 ```javascript 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/604b5e7f-309e-40db-b95b-4fac746c5153.svg', ); layer.shape('00'); ``` ⚠️ 符号图的 `ID` 不能与点图层已有 shape 名称相同,比如不能设置 `circle`。 同样符号图 `shape` 也支持数据映射 ```javascript const scatter = new PointLayer() .source(data) .shape('name', (v) => { switch (v) { case 'p1': return '00'; case 'p2': return '01'; } }) .size(5) .style({ opacity: 0.3, strokeWidth: 1, }); ``` ⚠️ 符号图不应该设置 `color` 传入颜色,`color` 设置的颜色会覆盖图片的颜色。 ⚠️ 为了得到更好的现实效果(图片清晰,无明显锯齿),我们在选择图片以及设置图标大小的时候应保持相当,或者在 L7 图层中设置的图标大小略小于实际图片的像素大小。 [在线案例](/zh/examples/point/image/image/) ### style #### billboard 1. 默认通过 `PointLayer` 实例化的 `image` 本质上是精灵贴图,因此有始终面向相机的特性,同时贴图的大小也收到设备的限制。 2. 由于精灵始终面向相机,因此我们也无法自定义配置 `image` 的旋转角度。 为了解决上述的两个问题(1. 大小受限,2. 无法自定义旋转角度),我们单独提供了非精灵模式`billboard` 的模式。 只需要在 style 中配置 billboard 为 `false` ```javascript const imageLayer = new PointLayer({ layerType: 'fillImage' }) .source(data, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('name', ['00', '01', '02']) .style({ rotation: 0, billboard: false, }) .size(45); ``` ##### rotation 我们支持使用 `rotation` 自定义配置图标的旋转角度(顺时针方向、角度制)。 - `rotation`: number|undefined // 角度单位 0-360 ```ts layer.style({ rotation: 90, }); ``` rotation 支持常量,也支持数据映射 ```ts layer.style({ rotation: { field: 'rotate', value: [0, 360], }, }); ``` ```tsx layer.style({ rotation: { field: 'rotate', value: (rotate) => { return rotate; }, }, }); ``` [在线案例](/zh/examples/point/image/image/) 符号图的 非 billboard 模式支持 `rotation` 方法根据数据映射旋转角度。 ```javascript const imageLayer = new PointLayer() .source(data) .shape('wind', (wind) => { if (wind === 'up') { return 'arrBlue'; } return 'arrRed'; }) .size(15) .style({ rotation: 0, // billboard: false, }); scene.addLayer(imageLayer); ``` [在线案例](/zh/examples/point/image/monsoon/) #### 快速 issue - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/quick_issue/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/quick_issue.md - Description: 快速 issue --- title: "快速 issue" description: "快速 issue" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/quick_issue/" --- ### 为什么提 Issue - Issue 是开放的,看到的同学可以解答,提出想法,提升 Issue 的解决效率 - Issue 能够做到很好的任务管理 - 如果该问题得到解决,遇到同样问题是人,可以参考解决。 ### 如何提 issue 1. 提交问题前,请先阅读 https://l7.antv.antgroup.com/tutorial/quickstart 上的文档。 2. 我们推荐如果是小问题(错别字修改,小的 bug fix)直接提交 PR。 3. 如果是一个新需求,请提供:详细需求描述,最好是有伪代码实现。 4. 如果是一个 BUG,请提供:复现步骤,错误日志以及相关配置,并尽量填写下面的模板中的条目。 5. 如果可以,请提供尽可能精简的 codesandbox 链接,可使用 codesandbox 模板 https://codesandbox.io/s/45smpb,方便我们排查问题。 6. 扩展阅读:[如何向开源项目提交无法解答的问题](https://zhuanlan.zhihu.com/p/25795393) ### 如果提供复现 demo 复现demo 是指可运行的代码环境,不是复制代码,推荐使用 https://codesandbox.io/s/45smpb ,同时官网提供了自动跳转到codebox 的能力。 - L7 demo 页面找到,需要复现的图层或者相似的demo - 在 sandbox 打开 当前demo 你可能没有注意到,代码区的上方有一排工具按钮。 点击左侧第三个按钮,你就进入了 `codesandbox`。  你发现你进入了一个在线的代码编辑器,在这里面你可以修改代码,复现你发现的问题,然后保存,并在链接复制到 Issue 内容中。 ### 现在你可以去 L7 仓库提 issue https://github.com/antvis/L7/issues/new 如果还没有 star L7,可顺手点个 star。 #### 文本标注 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/text/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/text.md - Description: 文本标注 --- title: "文本标注" description: "文本标注" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/text/" --- 点图层支持绘制文本标注。 ### 实现 下面我们来介绍如何绘制一个常见的文本标注地图。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/text/point-text/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [110, 36], style: 'light', zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data.list, { parser: { type: 'json', x: 'j', y: 'w', }, }) .shape('m', 'text') .size(12) .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, // 描边宽度 }); scene.addLayer(pointLayer); }); }); ``` ### shape(field: name: shapeType: 'text'): ILayer - `field` 标注的字段名称。 - `shapeType` 默认值为 `text`。 ```javascript layer.shape('name', 'text'); ``` ### style - textAnchor `string` 文本相对锚点的位置 `'right' | 'top-right' | 'left' | 'bottom-right' | 'left' | 'top-left' | 'bottom-left' | 'bottom' | 'bottom-right' | 'bottom-left' | 'top' | 'top-right' | 'top-left' | 'center';` - padding: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 - spacing: number 文本间隔 - stroke: `string`; 描边颜色 - strokeWidth `number` 描边宽度 - strokeOpacity `number` 描边透明度 - fontWeight `string` 字体粗细 - fontFamily `string` 字号 - textOffset `[number, number]` 文本偏移量 - textAllowOverlap: `boolean` 是否允许文字遮盖 - raisingHeight 设置文本标注的抬升高度 #### iconfont 标注 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/iconfont/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/iconfont.md - Description: iconfont 标注 --- title: "iconfont 标注" description: "iconfont 标注" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/iconfont/" --- 点图层除了支持绘制文字标注之外还支持通过绘制文字的方式绘制建简单的图标,即绘制 `iconfont`。通过文字方式绘制的简单图标,我们可以 `color` 方法直接修改颜色。 ### 实现 下面我们来介绍如何绘制一个简单的 `iconfont` 图标点图层。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/text/iconfont/) ```javascript // 指定 iconfont 映射为字体样式的名称 const fontFamily = 'iconfont'; // 指定 iconfont 字体文件 const fontPath = '//at.alicdn.com/t/font_2534097_fcae9o2mxbv.woff2?t=1622200439140'; // 全局添加资源 scene.addFontFace(fontFamily, fontPath); // 全局添加 iconfont 字段的映射 scene.addIconFont('icon1', ''); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/70408903-80db-4278-a318-461604acb2df.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data.list, { parser: { type: 'json', x: 'j', y: 'w', }, }) .shape('icon', 'text') // 指定需要映射字段为 icon、shape 类型和普通的文字标注一样为 text .size(20) .color('w', ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99']) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [40, 0], // 文本相对锚点的偏移量 [水平, 垂直] padding: [0, 0], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#ffffff', // 描边颜色 fontFamily, iconfont: true, // 开启 iconfont 映射 }); scene.addLayer(pointLayer); }); }); ``` 1. `iconfont` 绘制的是 `unicode` 图标,在使用的时候需要提前指定对应的 `unicode` 映射文件。 2. 关于 `iconfont` 资源使用可以前往 `iconfont` 官网 [官网传送门](https://iconfont.cn/)。 ### shape(field: string, shapeType: 'text'): ILayer `iconfont` 其实就是特殊的文本标注,因此 `shape` 的用法和普通文本标注的用法保持一致。 - `field` 标注的字段名称。 - `shapeType` 默认为 `text`。 ```javascript layer.shape('iconfontField', 'text'); ``` ### style 我们在使用 `iconfont` 绘制简单图标的时候需要在 `style` 方法中将 `iconfont` 参数设置为 `true`。 ✨ iconfont 其他 style 参数的使用和普通的文本标注的参数保持一致。 #### 复合图表地图 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/chart/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/chart.md - Description: 复合图表地图 --- title: "复合图表地图" description: "复合图表地图" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/chart/" --- 我们在通过自定义 `Marker` 代替点图层节点的时候剋插入实现自定义图表,如使用二维统计图表代替点状符号。复合图表地图中常用扩展图形有柱状图、曲线图、玫瑰图等 ### 实现 下面我们来介绍如何绘制一个简单的地图复合图表。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/chart/bar/) ```javascript import { Scene, Marker } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import * as G2 from '@antv/g2'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [2.6125016864608597, 49.359131], zoom: 4.19, }), }); scene.on('loaded', () => { addChart(); scene.render(); }); function addChart() { fetch('https://gw.alipayobjects.com/os/basement_prod/0b96cca4-7e83-449a-93d0-2a77053e74ab.json') .then((res) => res.json()) .then((data) => { data.nodes.forEach(function (item) { const el = document.createElement('div'); const total = item.gdp.Agriculture + item.gdp.Industry + item.gdp.Service; const size = Math.min(parseInt(total / 30000, 10), 70); if (size < 30) { return; } const itemData = [ { item: 'Agriculture', count: item.gdp.Agriculture, percent: item.gdp.Agriculture / total, }, { item: 'Industry', count: item.gdp.Industry, percent: item.gdp.Industry / total, }, { item: 'Service', count: item.gdp.Service, percent: item.gdp.Service / total, }, ]; const chart = new G2.Chart({ container: el, width: size, height: size, render: 'svg', padding: 0, }); chart.legend(false); chart.source(itemData); chart.tooltip(false); chart.axis('count', { grid: false }); chart .interval() .position('item*count') .color('item', ['#5CCEA1', '#5D7092', '#5B8FF9']) .opacity(1); chart.render(); const marker = new Marker({ element: el }).setLnglat({ lng: item.coordinates[0], lat: item.coordinates[1], }); scene.addMarker(marker); }); }); } ``` #### Marker - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/mark/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/mark.md - Description: Marker --- title: "Marker" description: "Marker" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/mark/" --- 地图上的点可以是自定义的 `DOM`,我们将自定的 `DOM` 称为 `Marker` 。 ### 实现 下面我们来介绍如何绘制一个简单的 `Marker` 图层。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/component/marker/marker/) ```javascript import { Scene, Marker } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [105.790327, 36.495636], zoom: 4, }), }); scene.on('loaded', () => { addMarkers(); scene.render(); }); function addMarkers() { fetch('https://gw.alipayobjects.com/os/basement_prod/67f47049-8787-45fc-acfe-e19924afe032.json') .then((res) => res.json()) .then((nodes) => { for (let i = 0; i < nodes.length; i++) { if (nodes[i].g !== '1' || nodes[i].v === '') { continue; } const el = document.createElement('label'); el.className = 'labelclass'; el.textContent = nodes[i].v + '℃'; el.style.background = getColor(nodes[i].v); el.style.borderColor = getColor(nodes[i].v); const marker = new Marker({ element: el, }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); scene.addMarker(marker); } }); } function getColor(v) { return v > 50 ? '#800026' : v > 40 ? '#BD0026' : v > 30 ? '#E31A1C' : v > 20 ? '#FC4E2A' : v > 10 ? '#FD8D3C' : v > 5 ? '#FEB24C' : v > 0 ? '#FED976' : '#FFEDA0'; } ``` ### 使用文档 [Marker 文档](/zh/api/component/marker) [MarkerLayer 文档](/zh/api/component/marker_layer) #### 简单点 - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/point/simple/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/point/simple.md - Description: 简单点 --- title: "简单点" description: "简单点" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/point/simple/" --- 点图层支持精灵模式的简单点,精灵模式的点图层效率更高,点始终面向相机。 ### 实现 下面我们来介绍如何绘制一个简单点图层。 - 你可以在 `L7` 官网上找到[在线案例](/zh/examples/point/simple/simple/) ```javascript import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 20, center: [ 120, 20 ], zoom: 3 }) }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json') .then(res => res.json()) .then(data => { const pointLayer = new PointLayer({}) .source(data) .shape('simple') .size(15) .color('mag', mag => mag > 4.5 ? '#5B8FF9' : '#5CCEA1';) .style({ opacity: 0.6, strokeWidth: 3 }); scene.addLayer(pointLayer); }); }); ``` ### shape 简单点图层使用的 `shape` 参数固定为 `simple`。 ### use - 简单点图层的使用和一般的点图层表现一致 - 简单点图层的实质是精灵贴图,因此简单点图层始终面向相机(普通的 2D 点图层保持面向上) - 🌟 当用户对点图层的朝向没有要求或是对点图层的可视化效果要求比较简单,那么推荐尽量使用简单点图层,可以节省大量性能 - 🌟 简单点图层由于实质是精灵贴图,因此有大小限制:一般是 [1, 64],不同设备之间存在差异 ```javascript // L7 提供了查询方法快速查看 scene.getPointSizeRange(); // Float32Array - [min, max] ``` #### FAQ - Canonical page: https://l7.antv.antgroup.com/zh/tutorial/FAQ/ - Markdown source: https://l7.antv.antgroup.com/zh/tutorial/FAQ.md - Description: FAQ --- title: "FAQ" description: "FAQ" language: "zh" canonical: "https://l7.antv.antgroup.com/zh/tutorial/FAQ/" --- ### 项目中 L7 各个依赖包版本不一致导致报错 ```js Error: Cannot apply @injectable decorator multiple times. ``` 🌟 解决方法: 删除 `node_modules` 下所有不同版本的 `L7` 包,重新安装启动即可。 ### 禁止地图交互 1. 初始化的时候可以在 `map` 配置项设置 - 高德地图可查看 https://lbs.amap.com/api/javascript-api/reference/map - mapbox https://docs.mapbox.com/mapbox-gl-js/api/#map 2. 加载完成后设置 调用 `scene` 的 [setMapStatus](/zh/api/scene/#setmapstatus) 方法 ### webcontext lost 1. 浏览器存在 `webgl` 实例上限,一般浏览器为 16 个,因此浏览器中可以存在的地图实例是有限的。 2. 在销毁地图后需要调用 `scene.destroy();` 对 `webgl` 实例进行销毁。 ## Examples ### 公交线路插件 - zh page: https://l7.antv.antgroup.com/zh/examples/amap-plugin/bus/busstop/ - Source path: examples/amap-plugin/bus/demo/busstop.js ```js import { LineLayer, PointLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [116.475, 39.985], zoom: 12.2, plugin: ['AMap.ToolBar', 'AMap.LineSearch'], }), }); scene.addImage( 'road', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); scene.addImage( 'start', 'https://gw.alipayobjects.com/zos/bmw-prod/1c301f25-9bb8-4e67-8d5c-41117c877caf.svg', ); scene.addImage( 'end', 'https://gw.alipayobjects.com/zos/bmw-prod/f3db4998-e657-4c46-b5ab-205ddc12031f.svg', ); scene.addImage( 'busStop', 'https://gw.alipayobjects.com/zos/bmw-prod/54345af2-1d01-43e1-9d11-cd9bb953202c.svg', ); scene.on('loaded', () => { window.AMap.plugin(['AMap.ToolBar', 'AMap.LineSearch'], () => { scene.map.addControl(new AMap.ToolBar()); const linesearch = new AMap.LineSearch({ pageIndex: 1, // 页码,默认值为1 pageSize: 1, // 单页显示结果条数,默认值为20,最大值为50 city: '北京', // 限定查询城市,可以是城市名(中文/中文全拼)、城市编码,默认值为『全国』 extensions: 'all', // 是否返回公交线路详细信息,默认值为『base』 }); // 执行公交路线关键字查询 linesearch.search('536', function (status, result) { // 打印状态信息status和结果信息result const { path, via_stops } = result.lineInfo[0]; const startPoint = [path[0]]; const endpoint = [path[path.length - 1]]; const budStopsData = via_stops.map((stop) => ({ lng: stop.location.lng, lat: stop.location.lat, name: stop.name, })); const data = [ { id: '1', coord: path.map((p) => [p.lng, p.lat]), }, ]; const busLine = new LineLayer({ blend: 'normal' }) .source(data, { parser: { type: 'json', coordinates: 'coord', }, }) .size(5) .shape('line') .color('rgb(99, 166, 242)') .texture('road') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ lineTexture: true, iconStep: 25, }); scene.addLayer(busLine); const startPointLayer = new PointLayer({ zIndex: 1 }) .source(startPoint, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('start') .size(20) .style({ offsets: [0, 25], }); scene.addLayer(startPointLayer); const endPointLayer = new PointLayer({ zIndex: 1 }) .source(endpoint, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('end') .size(25) .style({ offsets: [0, 25], }); scene.addLayer(endPointLayer); const busStops = new PointLayer() .source(budStopsData, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('busStop') .size(13) .style({ offsets: [20, 0], }); scene.addLayer(busStops); const busStopsName = new PointLayer() .source(budStopsData, { parser: { x: 'lng', y: 'lat', type: 'json', }, }) .shape('name', 'text') .size(12) .color('#000') .style({ textAnchor: 'left', textOffset: [80, 0], stroke: '#fff', strokeWidth: 1, }); scene.addLayer(busStopsName); }); }); }); ``` ### 卫星地图 - zh page: https://l7.antv.antgroup.com/zh/examples/amap-plugin/bus/satellite/ - Source path: examples/amap-plugin/bus/demo/satellite.js ```js import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [105, 30], zoom: 2, }), }); scene.on('loaded', () => { scene.map.add(new window.AMap.TileLayer.Satellite()); }); ``` ### xyz瓦片地图 - zh page: https://l7.antv.antgroup.com/zh/examples/amap-plugin/bus/xyztile/ - Source path: examples/amap-plugin/bus/demo/xyztile.js ```js import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [105, 30], zoom: 2, }), }); scene.on('loaded', () => { const xyzTileLayer = new window.AMap.TileLayer({ getTileUrl: 'https://wprd0{1,2,3,4}.is.autonavi.com/appmaptile?x=[x]&y=[y]&z=[z]&size=1&scl=1&style=8<ype=11', zIndex: 100, }); scene.map.add(xyzTileLayer); }); ``` ### 杭州市地图 - zh page: https://l7.antv.antgroup.com/zh/examples/choropleth/administrative/hangzhou-city/ - Source path: examples/choropleth/administrative/demo/hangzhou-city.ts ```ts import { GaodeMap, Scene } from '@antv/l7'; import { Choropleth } from '@antv/l7plot'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'blank', center: [120.19382669582967, 30.258134], zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/alisis/geo-data-v0.1.1/administrative-data/area-list.json') .then((response) => response.json()) .then((list) => { const data = list .filter(({ level, parent }) => level === 'district' && parent === 330100) .map((item) => ({ ...item, value: Math.random() * 5000 })); const choropleth = new Choropleth({ source: { data, joinBy: { sourceField: 'adcode', geoField: 'adcode', }, }, viewLevel: { level: 'city', adcode: 330100, }, autoFit: true, color: { field: 'value', value: ['#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70'], scale: { type: 'quantize' }, }, style: { opacity: 1, stroke: '#ccc', lineWidth: 0.6, lineOpacity: 1, }, label: { visible: true, field: 'name', style: { fill: '#000', opacity: 0.8, fontSize: 10, stroke: '#fff', strokeWidth: 1.5, textAllowOverlap: false, padding: [5, 5], }, }, state: { active: { stroke: 'black', lineWidth: 1 }, }, tooltip: { items: ['name', 'adcode', 'value'], }, zoom: { position: 'bottomright', }, legend: { position: 'bottomleft', }, }); choropleth.addToScene(scene); }); }); ``` ### 西湖区地图 - zh page: https://l7.antv.antgroup.com/zh/examples/choropleth/administrative/xihu-district/ - Source path: examples/choropleth/administrative/demo/xihu-district.ts ```ts import { GaodeMap, Scene } from '@antv/l7'; import { Choropleth } from '@antv/l7plot'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'blank', center: [120.19382669582967, 30.258134], zoom: 3, }), }); const choropleth = new Choropleth({ source: { data: [{ adcode: 330106, value: 200 }], joinBy: { sourceField: 'adcode', geoField: 'adcode', }, }, viewLevel: { level: 'district', adcode: 330106, }, autoFit: true, color: { field: 'value', value: ['#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70'], scale: { type: 'quantize' }, }, style: { opacity: 1, stroke: '#ccc', lineWidth: 0.6, lineOpacity: 1, }, label: { visible: true, field: 'name', style: { fill: '#000', opacity: 0.8, fontSize: 10, stroke: '#fff', strokeWidth: 1.5, textAllowOverlap: false, padding: [5, 5], }, }, state: { active: { stroke: 'black', lineWidth: 1 }, }, tooltip: { items: ['name', 'adcode', 'value'], }, zoom: { position: 'bottomright', }, legend: { position: 'bottomleft', }, }); scene.on('loaded', () => { choropleth.addToScene(scene); }); ``` ### 浙江省地图 - zh page: https://l7.antv.antgroup.com/zh/examples/choropleth/administrative/zhejiang-province/ - Source path: examples/choropleth/administrative/demo/zhejiang-province.ts ```ts import { GaodeMap, Scene } from '@antv/l7'; import { Choropleth } from '@antv/l7plot'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'blank', center: [120.19382669582967, 30.258134], zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/alisis/geo-data-v0.1.1/administrative-data/area-list.json') .then((response) => response.json()) .then((list) => { const data = list .filter(({ level, parent }) => level === 'city' && parent === 330000) .map((item) => ({ ...item, value: Math.random() * 5000 })); const choropleth = new Choropleth({ source: { data, joinBy: { sourceField: 'adcode', geoField: 'adcode', }, }, viewLevel: { level: 'province', adcode: 330000, }, autoFit: true, color: { field: 'value', value: ['#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70'], scale: { type: 'quantize' }, }, style: { opacity: 1, stroke: '#ccc', lineWidth: 0.6, lineOpacity: 1, }, label: { visible: true, field: 'name', style: { fill: '#000', opacity: 0.8, fontSize: 10, stroke: '#fff', strokeWidth: 1.5, textAllowOverlap: false, padding: [5, 5], }, }, state: { active: { stroke: 'black', lineWidth: 1 }, }, tooltip: { items: ['name', 'adcode', 'value'], }, zoom: { position: 'bottomright', }, legend: { position: 'bottomleft', }, }); choropleth.addToScene(scene); }); }); ``` ### 浙江省县级地图 - zh page: https://l7.antv.antgroup.com/zh/examples/choropleth/administrative/zhejiang-province-district/ - Source path: examples/choropleth/administrative/demo/zhejiang-province-district.ts ```ts import { GaodeMap, Scene } from '@antv/l7'; import { Choropleth } from '@antv/l7plot'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'blank', center: [120.19382669582967, 30.258134], zoom: 3, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/alisis/geo-data-v0.1.1/administrative-data/area-list.json') .then((response) => response.json()) .then((list) => { const data = list .filter(({ level }) => level === 'district') .map((item) => ({ ...item, value: Math.random() * 5000 })); const choropleth = new Choropleth({ source: { data, joinBy: { sourceField: 'adcode', geoField: 'adcode', }, }, viewLevel: { level: 'province', adcode: 330000, granularity: 'district', }, autoFit: true, color: { field: 'value', value: ['#B8E1FF', '#7DAAFF', '#3D76DD', '#0047A5', '#001D70'], scale: { type: 'quantize' }, }, style: { opacity: 1, stroke: '#ccc', lineWidth: 0.6, lineOpacity: 1, }, label: { visible: true, field: 'name', style: { fill: '#000', opacity: 0.8, fontSize: 10, stroke: '#fff', strokeWidth: 1.5, textAllowOverlap: false, padding: [5, 5], }, }, state: { active: { stroke: 'black', lineWidth: 1 }, }, tooltip: { items: ['name', 'adcode', 'value'], }, zoom: { position: 'bottomright', }, legend: { position: 'bottomleft', }, }); choropleth.addToScene(scene); }); }); ``` ### ExportImage 导出图片 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/exportimage/ - Source path: examples/component/control/demo/exportimage.ts ```ts import { ExportImage, GaodeMap, PolygonLayer, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, WebGLParams: { preserveDrawingBuffer: true, }, }), }); scene.on('loaded', () => { const polygonLayer = new PolygonLayer({}); polygonLayer .source({ type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [120.143575, 30.239811], [120.143575, 30.247856], [120.151213, 30.247856], [120.151213, 30.239811], [120.143575, 30.239811], ], ], }, }, ], }) .color('#ff0000') .style({ opacity: 0.5, }); scene.addLayer(polygonLayer); const exportImage = new ExportImage({ onExport: (base64) => { alert(base64); }, }); scene.addControl(exportImage); }); ``` ### Fullscreen 全屏 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/fullscreen/ - Source path: examples/component/control/demo/fullscreen.ts ```ts import { Fullscreen, GaodeMap, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const fullscreen = new Fullscreen(); scene.addControl(fullscreen); }); ``` ### GeoLocate 定位 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/geolocate/ - Source path: examples/component/control/demo/geolocate.ts ```ts import { GaodeMap, GeoLocate, Scene } from '@antv/l7'; import gcoord from 'gcoord'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const geoLocate = new GeoLocate({ transform: (position) => { // 将获取到基于 WGS84 地理坐标系 的坐标转成 GCJ02 坐标系 return gcoord.transform(position, gcoord.WGS84, gcoord.GCJ02); }, }); scene.addControl(geoLocate); }); ``` ### LayerSwitch 图层显隐控制 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/layerswitch/ - Source path: examples/component/control/demo/layerswitch.ts ```ts import { GaodeMap, LayerSwitch, LineLayer, PolygonLayer, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const polygonLayer = new PolygonLayer({ name: '填充图层', }); polygonLayer .source({ type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [120.143575, 30.239811], [120.143575, 30.247856], [120.151213, 30.247856], [120.151213, 30.239811], [120.143575, 30.239811], ], ], }, }, ], }) .color('#ff0000') .style({ opacity: 0.5, }); scene.addLayer(polygonLayer); const lineLayer = new LineLayer({ name: '边框图层', }); lineLayer .source({ type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [ [ [120.143575, 30.239811], [120.143575, 30.247856], [120.151213, 30.247856], [120.151213, 30.239811], [120.143575, 30.239811], ], ], }, }, ], }) .color('#700000') .size(2); scene.addLayer(lineLayer); const layerSwitch = new LayerSwitch({ layers: [polygonLayer, lineLayer], }); scene.addControl(layerSwitch); }); ``` ### LayerSwitch 图层显隐控制(展示图层图片) - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/layerswitch1/ - Source path: examples/component/control/demo/layerswitch1.ts ```ts import { GaodeMap, LayerSwitch, RasterLayer, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const url1 = 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&gl=CN&x={x}&y={y}&z={z}'; const rasterLayer1 = new RasterLayer({ zIndex: 1, }).source(url1, { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 0, }, }); const url2 = 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=h&gl=CN&x={x}&y={y}&z={z}'; const rasterLayer2 = new RasterLayer({ zIndex: 1, }).source(url2, { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 0, }, }); scene.addLayer(rasterLayer1); scene.addLayer(rasterLayer2); const layerSwitch = new LayerSwitch({ layers: [ { layer: rasterLayer1, name: '遥感影像图层', img: 'https://mdn.alipayobjects.com/huamei_k6sfo0/afts/img/A*fG9HQpyNuv0AAAAAAAAAAAAADjWqAQ/original', }, { layer: rasterLayer2, name: '文字标注图层', img: 'https://mdn.alipayobjects.com/huamei_k6sfo0/afts/img/A*CP5pQY_8Q_YAAAAAAAAAAAAADjWqAQ/original', }, ], }); scene.addControl(layerSwitch); }); ``` ### Logo - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/logo/ - Source path: examples/component/control/demo/logo.ts ```ts import { GaodeMap, Logo, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), // 关闭默认 L7 Logo logoVisible: false, }); scene.on('loaded', () => { const logo = new Logo(); scene.addControl(logo); }); ``` ### MapTheme 地图样式切换 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/maptheme/ - Source path: examples/component/control/demo/maptheme.ts ```ts import { GaodeMap, MapTheme, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const mapTheme = new MapTheme(); scene.addControl(mapTheme); }); ``` ### MouseLocation 鼠标经纬度 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/mouselocation/ - Source path: examples/component/control/demo/mouselocation.ts ```ts import { GaodeMap, MouseLocation, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const mouseLocation = new MouseLocation({ position: 'bottomright', }); scene.addControl(mouseLocation); }); ``` ### Scale 比例尺 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/scale/ - Source path: examples/component/control/demo/scale.ts ```ts import { GaodeMap, Scale, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), logoVisible: false, }); scene.on('loaded', () => { const scale = new Scale(); scene.addControl(scale); }); ``` ### Swipe 卷帘对比 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/swipe/ - Source path: examples/component/control/demo/swipe.ts ```ts import { GaodeMap, RasterLayer, Scene, Swipe } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [127.5671666579043, 7.445038892195569], zoom: 2.632456779444394, }), }); scene.on('loaded', () => { // 地形地图图层 const leftLayer = new RasterLayer({}).source( 'https://tiles{1-3}.geovisearth.com/base/v1/ter/{z}/{x}/{y}?format=webp&tmsIds=w&token=b2a0cfc132cd60b61391b9dd63c15711eadb9b38a9943e3f98160d5710aef788', { parser: { maxZoom: 21, minZoom: 3, type: 'rasterTile', tileSize: 256, zoomOffset: 0, }, }, ); // 影像地图图层 const rightLayer = new RasterLayer({}).source( 'https://tiles{1-3}.geovisearth.com/base/v1/img/{z}/{x}/{y}?format=webp&tmsIds=w&token=b2a0cfc132cd60b61391b9dd63c15711eadb9b38a9943e3f98160d5710aef788', { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 0, }, }, ); scene.addLayer(leftLayer); scene.addLayer(rightLayer); const swipe = new Swipe({ orientation: 'vertical', ratio: 0.5, layers: [leftLayer], rightLayers: [rightLayer], }); scene.addControl(swipe); }); ``` ### 双屏对比 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/syncscene/ - Source path: examples/component/control/demo/syncscene.ts ```ts import { GaodeMap, HeatmapLayer, PointLayer, Scene } from '@antv/l7'; import { isNumber } from 'lodash-es'; // 通过 Scene 获取到地图引擎类型 function getMapType(scene) { const mapVersion = scene.getMapService().version; return mapVersion?.includes('MAPBOX') ? 'Mapbox' : 'Gaode'; } // 根据不同地图引擎类型,设置地图的状态「缩放层级、地图中心点、旋转角、倾角」 const updateSceneStatus = ( scene, status = { zoom, center, pitch, rotation, }, ) => { const mapType = getMapType(scene); const { zoom, center, pitch, rotation } = status; if (mapType === 'Gaode') { const map = scene?.map; // 高德地图关闭动画效果 if (center) map.setCenter(center, true); if (isNumber(zoom)) map?.setZoom(zoom + 1, true); if (isNumber(rotation)) map?.setRotation(360 - rotation, true); if (isNumber(pitch)) map?.setPitch(pitch, true); } else { if (isNumber(zoom)) scene?.setZoom(zoom); if (center) scene?.setCenter(center); if (isNumber(rotation)) scene.setRotation(rotation); if (isNumber(pitch)) scene?.setPitch(pitch); } }; export function syncScene(scenes, options = {}) { const { zoomGap = 0, mainIndex = 0 } = options ?? {}; const listeners = []; let handlers = []; // 添加地图事件监听 const listen = (index) => { const scene = scenes[index]; scene.on('mapmove', handlers[index]); // Gaode 地图调整倾角和旋转角的事件 scene.on('dragging', handlers[index]); // Mapbox 地图调整倾角和旋转角的事件 scene.on('rotate', handlers[index]); scene.on('zoomchange', handlers[index]); return () => { scene.off('mapmove', handlers[index]); scene.off('dragging', handlers[index]); scene.off('zoomchange', handlers[index]); scene.off('rotate', handlers[index]); }; }; const clearListener = () => { listeners?.forEach((call) => call()); listeners.length = 0; }; // 根据指定索引的 scene 同步其他 scene 状态 const moveScenePosition = (index) => { const movedScene = scenes[index]; const center = movedScene.getCenter(); const zoom = movedScene.getZoom(); const rotation = movedScene.getRotation(); const pitch = movedScene.getPitch(); /** * 根据当前地图是否为主地图,分两种情况 * 1. 非主地图,则其他非主地图 zoom 设置当前 zoom ,主地图设置为 zoom - zoomGap * 2. 主地图,则其他非主地图 zoom 设置为 zoom + zoomGap */ const isMovedMainScene = index === mainIndex; scenes.forEach((scene, num) => { if (num !== index) { // 当前需要同步的状态是不是主地图 const sceneZoom = isMovedMainScene ? zoom + zoomGap : num === mainIndex ? zoom - zoomGap : zoom; updateSceneStatus(scene, { zoom: sceneZoom, center: [center.lng, center.lat], rotation, pitch, }); } }); }; const syncHandler = (index) => { clearListener(); moveScenePosition(index); initListener(); }; function initListener() { handlers = scenes.map((value, index) => { // 每个地图有自己的状态同步函数 return syncHandler.bind(null, index); }); scenes.forEach((scene, index) => { // 给每个地图绑定监听 listeners.push(listen(index)); }); } // 初始化,先将所有地图状态同步。 scenes.forEach((value, index) => { moveScenePosition(index); }); // 添加地图事件监听 initListener(); // 返回清除绑定的监听事件函数 return clearListener; } const mapDiv = document.getElementById('map'); if (mapDiv) { mapDiv.style.cssText = 'display: flex; height: 700px'; // 创建第一个新div并设置一些属性或内容 const newMapDiv1 = document.createElement('div'); newMapDiv1.style.cssText = 'width: 50%; height: 700px; position: relative; margin-right: 5px;'; newMapDiv1.id = 'map1'; // 给新div设置id // 创建第二个新div并设置一些属性或内容 const newMapDiv2 = document.createElement('div'); newMapDiv2.style.cssText = 'width: 50%; height: 700px; position: relative; margin-left: 5px;'; newMapDiv2.id = 'map2'; // 给新div设置id mapDiv.appendChild(newMapDiv1); mapDiv.appendChild(newMapDiv2); const scene = new Scene({ id: 'map1', map: new GaodeMap({ pitch: 0, style: 'normal', center: [114.07737552216226, 22.542656745583486], rotation: 90, zoom: 12.47985, }), // 关闭默认 L7 Logo logoVisible: false, }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/513add53-dcb2-4295-8860-9e7aa5236699.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data) .shape('circle') .size('h12', [2, 5]) .color( 'h12', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', ].reverse(), ); scene.addLayer(pointLayer); }); }); const scene1 = new Scene({ id: 'map2', map: new GaodeMap({ pitch: 0, style: 'normal', center: [114.07737552216226, 22.542656745583486], rotation: 90, zoom: 12.47985, }), // 关闭默认 L7 Logo logoVisible: false, }); scene1.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/513add53-dcb2-4295-8860-9e7aa5236699.json') .then((res) => res.json()) .then((data) => { const pointLayer = new HeatmapLayer({}) .source(data, { transforms: [ { type: 'hexagon', size: 400, field: 'h12', method: 'sum', }, ], }) .shape('hexagon') .style({ coverage: 0.9, angle: 0, }) .color( 'sum', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', ].reverse(), ); scene1.addLayer(pointLayer); }); }); syncScene([scene, scene1]); } ``` ### Zoom 缩放 - zh page: https://l7.antv.antgroup.com/zh/examples/component/control/zoom/ - Source path: examples/component/control/demo/zoom.ts ```ts import { GaodeMap, Scene, Zoom } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), }); scene.on('loaded', () => { const zoom = new Zoom(); scene.addControl(zoom); }); ``` ### MarkerLayer 聚合Marker - zh page: https://l7.antv.antgroup.com/zh/examples/component/marker/clustermarker/ - Source path: examples/component/marker/demo/clustermarker.js ```js import { Marker, MarkerLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [105.790327, 30], zoom: 2, }), }); scene.on('loaded', () => { addMarkers(); scene.render(); }); function addMarkers() { fetch('https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json') .then((res) => res.json()) .then((nodes) => { const markerLayer = new MarkerLayer({ cluster: true, }); for (let i = 0; i < nodes.features.length; i++) { const { coordinates } = nodes.features[i].geometry; const marker = new Marker().setLnglat({ lng: coordinates[0], lat: coordinates[1], }); markerLayer.addMarker(marker); } scene.addMarkerLayer(markerLayer); }); } ``` ### 默认 Marker - zh page: https://l7.antv.antgroup.com/zh/examples/component/marker/defaultmarker/ - Source path: examples/component/marker/demo/defaultmarker.js ```js import { Marker, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [105.790327, 36.495636], zoom: 4, }), }); scene.on('loaded', () => { addMarkers(); scene.render(); }); function addMarkers() { fetch('https://gw.alipayobjects.com/os/basement_prod/67f47049-8787-45fc-acfe-e19924afe032.json') .then((res) => res.json()) .then((nodes) => { for (let i = 0; i < nodes.length; i++) { if (nodes[i].g !== '1' || nodes[i].v === '') { continue; } const marker = new Marker().setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); scene.addMarker(marker); } }); } ``` ### 温度 - zh page: https://l7.antv.antgroup.com/zh/examples/component/marker/marker/ - Source path: examples/component/marker/demo/marker.js ```js import { Marker, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [105.790327, 36.495636], zoom: 4, }), }); scene.on('loaded', () => { addMarkers(); scene.render(); }); function addMarkers() { fetch('https://gw.alipayobjects.com/os/basement_prod/67f47049-8787-45fc-acfe-e19924afe032.json') .then((res) => res.json()) .then((nodes) => { for (let i = 0; i < nodes.length; i++) { if (nodes[i].g !== '1' || nodes[i].v === '') { continue; } const el = document.createElement('label'); el.className = 'labelclass'; el.textContent = nodes[i].v + '℃'; el.style.background = getColor(nodes[i].v); el.style.borderColor = getColor(nodes[i].v); const marker = new Marker({ element: el, }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); scene.addMarker(marker); } }); } function getColor(v) { return v > 50 ? '#800026' : v > 40 ? '#BD0026' : v > 30 ? '#E31A1C' : v > 20 ? '#FC4E2A' : v > 10 ? '#FD8D3C' : v > 5 ? '#FEB24C' : v > 0 ? '#FED976' : '#FFEDA0'; } ``` ### MarkerLayer 统一管理Marker - zh page: https://l7.antv.antgroup.com/zh/examples/component/marker/markerlayer/ - Source path: examples/component/marker/demo/markerlayer.js ```js import { Marker, MarkerLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [105.790327, 36.495636], zoom: 4, }), }); scene.on('loaded', () => { addMarkers(); scene.render(); }); function addMarkers() { fetch('https://gw.alipayobjects.com/os/basement_prod/67f47049-8787-45fc-acfe-e19924afe032.json') .then((res) => res.json()) .then((nodes) => { const markerLayer = new MarkerLayer(); for (let i = 0; i < nodes.length; i++) { if (nodes[i].g !== '1' || nodes[i].v === '') { continue; } const el = document.createElement('label'); el.className = 'labelclass'; el.textContent = nodes[i].v + '℃'; el.style.background = getColor(nodes[i].v); el.style.borderColor = getColor(nodes[i].v); const marker = new Marker({ element: el, }).setLnglat({ lng: nodes[i].x * 1, lat: nodes[i].y }); markerLayer.addMarker(marker); } scene.addMarkerLayer(markerLayer); }); } function getColor(v) { const colors = [ '#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32', ]; return v > 50 ? colors[7] : v > 40 ? colors[6] : v > 30 ? colors[5] : v > 20 ? colors[4] : v > 10 ? colors[3] : v > 5 ? colors[2] : v > 0 ? colors[1] : colors[0]; } ``` ### 图层气泡 自定义内容 - zh page: https://l7.antv.antgroup.com/zh/examples/component/popup/customcontent/ - Source path: examples/component/popup/demo/customcontent.ts ```ts import * as G2 from '@antv/g2'; import { GaodeMap, LayerPopup, PointLayer, Scene } from '@antv/l7'; const data: any[] = [ { lng: 120.132235, lat: 30.250868, value: 34.71314604052238, name: '坐标点1', }, { lng: 120.156236, lat: 30.260268, value: 96.807880210153, name: '坐标点2', }, { lng: 120.163014, lat: 30.251297, value: 29.615472482876815, name: '坐标点3', }, { lng: 120.15394, lat: 30.231489, value: 49.90316258911784, name: '坐标点4', }, { lng: 120.154596, lat: 30.24065, value: 45.788587061188466, name: '坐标点5', }, { lng: 120.150223, lat: 30.235078, value: 29.741111717098544, name: '坐标点6', }, { lng: 120.143992, lat: 30.229411, value: 40.241555782182935, name: '坐标点7', }, { lng: 120.136995, lat: 30.237439, value: 86.5369792415296, name: '坐标点8', }, ]; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), logoVisible: false, }); scene.on('loaded', () => { const pointLayer = new PointLayer({}); pointLayer .source(data, { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .color('value', ['#FFCCC6', '#CF1421']) .size(10) .shape('circle'); scene.addLayer(pointLayer); const div = document.createElement('div'); const chart = new G2.Chart({ container: div, autoFit: true, width: 200, height: 200, }); // 新建一个 view 用来单独渲染Annotation chart.coordinate('theta', { radius: 0.75, innerRadius: 0.5, }); chart.scale('percent', { formatter: (val) => { val = val * 100 + '%'; return val; }, }); chart.tooltip(false); // 声明需要进行自定义图例字段: 'item' chart.legend(false); chart.interval().adjust('stack').position('percent').color('item', ['#5B8FF9', '#797979']).style({ fillOpacity: 1, }); const layerPopup = new LayerPopup({ items: [ { layer: pointLayer, customContent: (e) => { const otherValue = 100 - e.value; chart.data([ { item: '值', count: e.value, percent: e.value / 100 }, { item: '', count: otherValue, percent: otherValue / 100 }, ]); chart.render(); return div; }, }, ], }); scene.addPopup(layerPopup); }); ``` ### LayerPopup 图层气泡 - zh page: https://l7.antv.antgroup.com/zh/examples/component/popup/layerpopup/ - Source path: examples/component/popup/demo/layerpopup.ts ```ts import { GaodeMap, LayerPopup, PointLayer, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), logoVisible: false, }); scene.on('loaded', () => { const pointLayer = new PointLayer({}); pointLayer .source( [ { lng: 120.132235, lat: 30.250868, value: 34.71314604052238, name: '坐标点1', }, { lng: 120.156236, lat: 30.260268, value: 96.807880210153, name: '坐标点2', }, { lng: 120.163014, lat: 30.251297, value: 29.615472482876815, name: '坐标点3', }, { lng: 120.15394, lat: 30.231489, value: 49.90316258911784, name: '坐标点4', }, { lng: 120.154596, lat: 30.24065, value: 45.788587061188466, name: '坐标点5', }, { lng: 120.150223, lat: 30.235078, value: 29.741111717098544, name: '坐标点6', }, { lng: 120.143992, lat: 30.229411, value: 40.241555782182935, name: '坐标点7', }, { lng: 120.136995, lat: 30.237439, value: 86.5369792415296, name: '坐标点8', }, ], { parser: { type: 'json', x: 'lng', y: 'lat', }, }, ) .color('value', ['#FFCCC6', '#CF1421']) .size(10) .shape('circle'); scene.addLayer(pointLayer); const layerPopup = new LayerPopup({ items: [ { layer: pointLayer, fields: [ { field: 'name', formatField: () => '名称', }, { field: 'value', formatField: () => '权值', formatValue: (val) => val.toFixed(2), }, 'lng', 'lat', ], }, ], }); scene.addPopup(layerPopup); }); ``` ### Popup 基础气泡 - zh page: https://l7.antv.antgroup.com/zh/examples/component/popup/popup/ - Source path: examples/component/popup/demo/popup.ts ```ts import { GaodeMap, Popup, Scene } from '@antv/l7'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'normal', center: [120.154672, 30.241095], zoom: 12, }), logoVisible: false, }); scene.on('loaded', () => { const popup = new Popup({ title: '自定义标题', html: 'Popup 示例的自定义内容', lngLat: { lng: 120.154672, lat: 30.241095, }, }); scene.addPopup(popup); }); ``` ### 图层点击 气泡 - zh page: https://l7.antv.antgroup.com/zh/examples/component/popup/popup2/ - Source path: examples/component/popup/demo/popup2.ts ```ts // @ts-ignore import { PointLayer, Popup, Scene } from '@antv/l7'; // @ts-ignore import { GaodeMap } from '@antv/l7-maps'; async function initMap() { const response = await fetch( 'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json', ); const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [121.4, 31.258134], zoom: 12, pitch: 0, style: 'normal', }), }); scene.addImage( '00', 'https://gw.alipayobjects.com/mdn/rms_fcd5b3/afts/img/A*g8cUQ7pPT9YAAAAAAAAAAAAAARQnAQ', ); scene.addImage( '01', 'https://gw.alipayobjects.com/mdn/rms_fcd5b3/afts/img/A*LTcXTLBM7kYAAAAAAAAAAAAAARQnAQ', ); scene.addImage( '02', 'https://gw.alipayobjects.com/zos/bmw-prod/904d047a-16a5-461b-a921-98fa537fc04a.svg', ); const data = await response.json(); const newData = data.map((item: any) => { item.type = ['00', '01', '02'][Math.floor(Math.random() * 3)]; return item; }); const imageLayer = new PointLayer({}) .source(newData, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('type', (v: any) => { return v; }) .active(false) .size(20); scene.addLayer(imageLayer); imageLayer.on('mousedown', (e) => { console.log('mousedown', e); }); const popup = new Popup({}); scene.addPopup(popup); imageLayer.on('click', (e) => { console.log(e); const { lng, lat } = e.lngLat; popup.setOptions({ title: e.feature.name, html: e.feature.name, lngLat: { lng, lat, }, }); }); } initMap(); ``` ### 客流图层 - zh page: https://l7.antv.antgroup.com/zh/examples/composite-layers/l7plot/flow-layer/ - Source path: examples/composite-layers/l7plot/demo/flow-layer.js ```js import { GaodeMapV2, LayerPopup, Scene } from '@antv/l7'; import { FlowLayer } from '@antv/l7-composite-layers'; // 详情可见:https://l7plot.antv.antgroup.com/api/composite-layers/flow-layer const scene = new Scene({ id: 'map', map: new GaodeMapV2({ pitch: 0, style: 'dark', center: [121.458794, 31.205302], zoom: 10.95, }), }); scene.on('loaded', async () => { const response = await fetch( 'https://gw.alipayobjects.com/os/bmw-prod/f4f3e99a-1d6c-4ab0-b08f-ec730c576b62.json', ); const data = await response.json(); const flowLayer = new FlowLayer({ source: { data, parser: { type: 'json', x: 'f_lon', y: 'f_lat', x1: 't_lon', y1: 't_lat', weight: 'weight', }, }, }); flowLayer.on('circleLayer:click', (e) => console.log('circle layer click', e)); flowLayer.on('lineLayer:click', (e) => console.log('line layer click', e)); scene && flowLayer.addTo(scene); const layerPopup = new LayerPopup({ items: [ { layer: 'circleLayer', fields: ['id', 'weight'], }, { layer: 'lineLayer', fields: ['id', 'weight'], }, ], }); scene.addPopup(layerPopup); }); ``` ### 字体标注图层 - zh page: https://l7.antv.antgroup.com/zh/examples/composite-layers/l7plot/icon-layer/ - Source path: examples/composite-layers/l7plot/demo/icon-layer.js ```js import { GaodeMap, Scene } from '@antv/l7'; import { IconFontLayer } from '@antv/l7-composite-layers'; // 详情可见:https://l7plot.antv.antgroup.com/api/composite-layers/icon-font-layer fetch('https://gw.alipayobjects.com/os/bmw-prod/9eb3f1b5-0c3b-49b2-8221-191d4ba8aa5e.json') .then((response) => response.json()) .then((data) => { const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'dark', zoom: 3, center: [120.19660949707033, 30.234747338474293], }), }); scene.on('loaded', () => { const iconLayer = new IconFontLayer({ id: 'iconImageLayer1', autoFit: true, source: { data, parser: { type: 'json', x: 'lng', y: 'lat', }, }, // color:{ // value:'red', // }, iconAtlas: { fontFamily: 'iconfont', fontPath: '//at.alicdn.com/t/font_2534097_ao9soua2obv.woff2?t=1622021146076', iconFonts: [ ['smallRain', ''], ['middleRain', ''], ['hugeRain', ''], ['sun', ''], ['cloud', ''], ], }, icon: { field: 'iconType', value: 'text', }, iconStyle: { textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left textOffset: [-10, 10], // 文本相对锚点的偏移量 [水平, 垂直] fontFamily: 'iconfont', textAllowOverlap: true, iconfont: true, }, fillColor: 'blue', radius: 40, opacity: 1, label: { visible: false, field: 'weather', style: { fill: '#fff', opacity: 0.6, fontSize: 12, textAnchor: 'top', textOffset: [0, 20], spacing: 1, padding: [5, 5], stroke: '#ffffff', strokeWidth: 0.3, strokeOpacity: 1.0, }, }, state: { active: { color: 'red', }, select: { radius: 20, opacity: 1, }, }, }); scene && iconLayer.addTo(scene); }); }); ``` ### 图片标注图层 - zh page: https://l7.antv.antgroup.com/zh/examples/composite-layers/l7plot/image-layer/ - Source path: examples/composite-layers/l7plot/demo/image-layer.js ```js import { GaodeMap, Scene } from '@antv/l7'; import { IconImageLayer } from '@antv/l7-composite-layers'; // 详情可见:https://l7plot.antv.antgroup.com/api/composite-layers/icon-image-layer fetch('https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json') .then((response) => response.json()) .then((data) => { const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 0, style: 'dark', zoom: 3, center: [120.19660949707033, 30.234747338474293], }), }); scene.on('loaded', () => { const iconLayer = new IconImageLayer({ id: 'iconImageLayer1', autoFit: true, source: { data, parser: { type: 'json', x: 'longitude', y: 'latitude', }, }, // color:{ // value:'red', // }, iconAtlas: { icon1: 'https://gw.alipayobjects.com/zos/basement_prod/604b5e7f-309e-40db-b95b-4fac746c5153.svg', icon2: 'https://gw.alipayobjects.com/zos/basement_prod/7aa1f460-9f9f-499f-afdf-13424aa26bbf.svg', }, icon: 'icon1', radius: { field: 'unit_price', value: [1, 20], }, opacity: 1, label: { field: 'name', state: { active: { color: 'blue', }, }, style: { fill: '#fff', opacity: 0.6, fontSize: 12, textAnchor: 'top', textOffset: [0, -40], spacing: 1, padding: [5, 5], stroke: '#ffffff', strokeWidth: 0.3, strokeOpacity: 1.0, }, }, state: { active: false, select: { radius: 20, opacity: 1, icon: 'icon2', }, }, }); scene && iconLayer.addTo(scene); }); }); ``` ### 绘制圆 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/basic/draw-circle/ - Source path: examples/draw/basic/demo/draw-circle.js ```js import { Scene } from '@antv/l7'; import { DrawCircle, DrawEvent } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [120.211944, 30.288946], zoom: 7.05, }), }); scene.on('loaded', () => { const drawCircle = new DrawCircle(scene, {}); drawCircle.enable(); drawCircle.on(DrawEvent.Change, (allFeatures) => { console.log(allFeatures); }); }); ``` ### 绘制线 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/basic/draw-line/ - Source path: examples/draw/basic/demo/draw-line.js ```js import { Scene } from '@antv/l7'; import { DrawEvent, DrawLine } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [120.211944, 30.288946], zoom: 7.05, }), }); scene.on('loaded', () => { const drawLine = new DrawLine(scene, { distanceOptions: {}, }); drawLine.enable(); drawLine.on(DrawEvent.Change, (allFeatures) => { console.log(allFeatures); }); }); ``` ### 绘制点 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/basic/draw-point/ - Source path: examples/draw/basic/demo/draw-point.js ```js import { Scene } from '@antv/l7'; import { DrawEvent, DrawPoint } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [120.211944, 30.288946], zoom: 7.05, }), }); scene.on('loaded', () => { const drawPoint = new DrawPoint(scene, {}); drawPoint.enable(); drawPoint.on(DrawEvent.Change, (allFeatures) => { console.log(allFeatures); }); setInterval(() => { console.log(scene.getZoom(), scene.getCenter()); }, 2000); }); ``` ### 绘制面 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/basic/draw-polygon/ - Source path: examples/draw/basic/demo/draw-polygon.js ```js import { Scene } from '@antv/l7'; import { DrawEvent, DrawPolygon } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [120.211944, 30.288946], zoom: 7.05, }), }); scene.on('loaded', () => { const drawPolygon = new DrawPolygon(scene, { areaOptions: {}, }); drawPolygon.enable(); drawPolygon.on(DrawEvent.Change, (allFeatures) => { console.log(allFeatures); }); }); ``` ### 绘制矩形 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/basic/draw-rect/ - Source path: examples/draw/basic/demo/draw-rect.js ```js import { Scene } from '@antv/l7'; import { DrawEvent, DrawRect } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [120.211944, 30.288946], zoom: 7.05, }), }); scene.on('loaded', () => { const drawRect = new DrawRect(scene, {}); drawRect.enable(); drawRect.on(DrawEvent.Change, (allFeatures) => { console.log(allFeatures); }); }); ``` ### 高德地图绘制 - zh page: https://l7.antv.antgroup.com/zh/examples/draw/control/amap/ - Source path: examples/draw/control/demo/amap.js ```js // https://gw.alipayobjects.com/zos/antvdemo/assets/2019_clip/ndvi_201905.tif import { Scene } from '@antv/l7'; import { ControlEvent, DrawControl } from '@antv/l7-draw'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [116.1608, 40.1119], zoom: 15, }), }); scene.on('loaded', () => { const tileLayer = new AMap.TileLayer.Satellite(); tileLayer.setMap(scene.map); const drawControl = new DrawControl(scene, {}); scene.addControl(drawControl); drawControl.on(ControlEvent.DrawChange, (changeType) => { console.log(changeType); }); }); ``` ### 飞线 - zh page: https://l7.antv.antgroup.com/zh/examples/earth/arc3d/flyline/ - Source path: examples/earth/arc3d/demo/flyline.js ```js import { EarthLayer, LineLayer, Scene } from '@antv/l7'; import { Earth } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Earth({}), }); // 地球模式下背景色默认为 #000 通过 setBgColor 方法我们可以设置可视化层的背景色 scene.setBgColor('#333'); const earthlayer = new EarthLayer() .source('https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', { parser: { type: 'image', }, }) .color('#2E8AE6') .shape('fill') .style({ globalOptions: { ambientRatio: 0.6, // 环境光 diffuseRatio: 0.4, // 漫反射 specularRatio: 0.1, // 高光反射 }, }) .animate(true); const atomLayer = new EarthLayer().color('#2E8AE6').shape('atomSphere'); const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere').style({ opacity: 0.7, }); scene.on('loaded', () => { scene.addLayer(earthlayer); scene.addLayer(atomLayer); scene.addLayer(bloomLayer); fetch('https://gw.alipayobjects.com/os/bmw-prod/20a69b46-3d6d-4ab5-b8b5-150b6aa52c88.json') .then((res) => res.json()) .then((flydata) => { const flyLine = new LineLayer({ blend: 'normal' }) .source(flydata, { parser: { type: 'json', coordinates: 'coord', }, }) .color('#b97feb') .shape('arc3d') .size(0.5) .active(true) .animate({ interval: 2, trailLength: 2, duration: 1, }) .style({ segmentNumber: 60, globalArcHeight: 20, }); scene.addLayer(flyLine); }); earthlayer.setEarthTime(4.0); }); ``` ### 高德地图 - zh page: https://l7.antv.antgroup.com/zh/examples/engine/three/amap-ant/ - Source path: examples/engine/three/demo/amap-ant.js ```js import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import * as THREE from 'three'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [111.4453125, 32.84267363195431], pitch: 45, rotation: 30, zoom: 12, }), }); scene.on('loaded', () => { scene.registerRenderService(ThreeRender); const threeJSLayer = new ThreeLayer({ enableMultiPassRenderer: false, onAddMeshes: (threeScene, layer) => { threeScene.add(new THREE.AmbientLight(0xffffff)); const sunlight = new THREE.DirectionalLight(0xffffff, 0.25); sunlight.position.set(0, 80000000, 100000000); sunlight.matrixWorldNeedsUpdate = true; threeScene.add(sunlight); const center = scene.getCenter(); const cubeGeometry = new THREE.BoxBufferGeometry(10000, 10000, 10000); const cubeMaterial = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); layer.setObjectLngLat(cube, [center.lng + 0.05, center.lat], 0); threeScene.add(cube); // 使用 Three.js glTFLoader 加载模型 const loader = new window.GLTFLoader(); loader.load( 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf', (gltf) => { const gltfScene = gltf.scene; setDouble(gltfScene); layer.adjustMeshToMap(gltfScene); // gltfScene.scale.set(1000, 1000, 1000) layer.setMeshScale(gltfScene, 1000, 1000, 1000); layer.setObjectLngLat(gltfScene, [center.lng, center.lat], 0); const animations = gltf.animations; if (animations && animations.length) { const mixer = new THREE.AnimationMixer(gltfScene); const animation = animations[2]; const action = mixer.clipAction(animation); action.play(); layer.addAnimateMixer(mixer); } // layer.setObjectLngLat(gltfScene, [center.lng + 0.05, center.lat] as ILngLat, 0) let t = 0; setInterval(() => { t += 0.01; layer.setObjectLngLat(gltfScene, [center.lng, center.lat + Math.sin(t) * 0.1], 0); }, 16); // 向场景中添加模型 threeScene.add(gltfScene); // 重绘图层 layer.render(); }, ); }, }).animate(true); scene.addLayer(threeJSLayer); }); function setDouble(object) { if (object.children && object.children.length && object.children.length > 0) { object.children.map((child) => setDouble(child)); } else if (object.material) { object.material.side = THREE.DoubleSide; } } ``` ### 基础图形与光照 - zh page: https://l7.antv.antgroup.com/zh/examples/engine/three/basic-geometry/ - Source path: examples/engine/three/demo/basic-geometry.js ```js import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import * as THREE from 'three'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [111.4453125, 32.84267363195431], pitch: 45, rotation: 30, zoom: 12, mapStyle: 'amap://styles/darkblue', }), }); scene.on('loaded', () => { scene.registerRenderService(ThreeRender); const threeJSLayer = new ThreeLayer({ enableMultiPassRenderer: false, onAddMeshes: (threeScene, layer) => { // 当前场景的中心 const center = scene.getCenter(); // 环境光照 threeScene.add(new THREE.AmbientLight(0xffffff, 0.2)); const sunlight = new THREE.DirectionalLight(0xff0000, 0.8); layer.setObjectLngLat(sunlight, [center.lng + 0.3, center.lat + 0.08], 1000); sunlight.matrixWorldNeedsUpdate = true; threeScene.add(sunlight); const directionalLightHelper = new THREE.DirectionalLightHelper(sunlight, 5); threeScene.add(directionalLightHelper); const box = createBoxGeometry(); box.scale.set(1000, 1000, 1000); box.rotation.set(0, 90, 0); layer.setObjectLngLat(box, [center.lng - 0.05, center.lat], 0); threeScene.add(box); const circle = createCircleGeometry(); circle.scale.set(100, 100, 1000); layer.setObjectLngLat(circle, [center.lng - 0.03, center.lat], 0); threeScene.add(circle); const cylinder = createCylinderGeometry(); cylinder.scale.set(100, 100, 100); layer.setObjectLngLat(cylinder, [center.lng - 0.015, center.lat], 0); threeScene.add(cylinder); const cone = createConeGeometry(); cone.scale.set(100, 100, 100); layer.setObjectLngLat(cone, [center.lng + 0.01, center.lat], 0); threeScene.add(cone); const plane = createPlaneGeometry(); plane.scale.set(1000, 1000, 1000); layer.setObjectLngLat(plane, [center.lng + 0.03, center.lat], 0); threeScene.add(plane); const shape = createShape(); shape.scale.set(100, 100, 100); layer.setObjectLngLat(shape, [center.lng + 0.03, center.lat], 0); threeScene.add(shape); const sphere = createSphereGeometry(); sphere.scale.set(10, 10, 10); layer.setObjectLngLat(sphere, [center.lng + 0.07, center.lat], 0); threeScene.add(sphere); const tube = createTube(); tube.scale.set(100, 100, 100); layer.setObjectLngLat(tube, [center.lng + 0.07, center.lat], 0); threeScene.add(tube); const points = createPoints(); points.scale.set(100, 100, 100); layer.setObjectLngLat(points, [center.lng + 0.11, center.lat], 0); threeScene.add(points); const line = createLine(); line.scale.set(100, 100, 100); layer.setObjectLngLat(line, [center.lng + 0.13, center.lat], 0); threeScene.add(line); const camera = layer.threeRenderService.getRenderCamera(); const cameraHelper = createCameraHelper(camera); layer.setObjectLngLat(plane, [center.lng, center.lat], 0); threeScene.add(cameraHelper); }, }).animate(true); scene.addLayer(threeJSLayer); }); function createBoxGeometry() { const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const cube = new THREE.Mesh(geometry, material); return cube; } function createCircleGeometry() { const geometry = new THREE.CircleGeometry(5, 32); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const circle = new THREE.Mesh(geometry, material); return circle; } function createCylinderGeometry() { const geometry = new THREE.CylinderGeometry(5, 5, 20, 32); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const cylinder = new THREE.Mesh(geometry, material); return cylinder; } function createConeGeometry() { const geometry = new THREE.ConeGeometry(5, 20, 32); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const cone = new THREE.Mesh(geometry, material); return cone; } function createPlaneGeometry() { const geometry = new THREE.PlaneGeometry(1, 1); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const plane = new THREE.Mesh(geometry, material); return plane; } function createShape() { const x = 0, y = 0; const heartShape = new THREE.Shape(); heartShape.moveTo(x + 5, y + 5); heartShape.bezierCurveTo(x + 5, y + 5, x + 4, y, x, y); heartShape.bezierCurveTo(x - 6, y, x - 6, y + 7, x - 6, y + 7); heartShape.bezierCurveTo(x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19); heartShape.bezierCurveTo(x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7); heartShape.bezierCurveTo(x + 16, y + 7, x + 16, y, x + 10, y); heartShape.bezierCurveTo(x + 7, y, x + 5, y + 5, x + 5, y + 5); const geometry = new THREE.ShapeGeometry(heartShape); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const mesh = new THREE.Mesh(geometry, material); return mesh; } function createSphereGeometry() { const geometry = new THREE.SphereGeometry(15, 32, 16); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const sphere = new THREE.Mesh(geometry, material); return sphere; } function createTube() { class CustomSinCurve extends THREE.Curve { constructor(scale = 1) { super(); this.scale = scale; } getPoint(t, optionalTarget = new THREE.Vector3()) { const tx = t * 3 - 1.5; const ty = Math.sin(2 * Math.PI * t); const tz = 0; return optionalTarget.set(tx, ty, tz).multiplyScalar(this.scale); } } const path = new CustomSinCurve(10); const geometry = new THREE.TubeGeometry(path, 20, 2, 8, false); const material = new THREE.MeshPhongMaterial({ color: 0xffffff, reflectivity: 0.8, shininess: 80, emissive: 0x049ef4, specular: 0x049ef4, }); const mesh = new THREE.Mesh(geometry, material); return mesh; } function createCameraHelper(camera = undefined) { const cameraObj = camera ?? new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const helper = new THREE.CameraHelper(cameraObj); return helper; } function createPoints() { const points = []; points.push(new THREE.Vector3(-10, 0, 0)); points.push(new THREE.Vector3(0, 10, 0)); points.push(new THREE.Vector3(10, 0, 0)); const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.PointsMaterial({ size: 200, color: 0x049ef4 }); const pointsGeometry = new THREE.Points(geometry, material); return pointsGeometry; } function createLine() { const material = new THREE.LineBasicMaterial({ color: 0x049ef4, linewidth: 6, }); const points = []; points.push(new THREE.Vector3(-10, 0, 0)); points.push(new THREE.Vector3(0, 10, 0)); points.push(new THREE.Vector3(10, 0, 0)); const geometry = new THREE.BufferGeometry().setFromPoints(points); const line = new THREE.Line(geometry, material); return line; } ``` ### 点击建筑 - zh page: https://l7.antv.antgroup.com/zh/examples/engine/three/space-click/ - Source path: examples/engine/three/demo/space-click.js ```js import { Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import { animate, easeInOut } from 'popmotion'; import * as THREE from 'three'; import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; function changeValue(startValue, endValue, duration = 500, callback, complete) { if (typeof startValue === 'number') { animate({ from: { v: startValue, }, to: { v: endValue, }, ease: easeInOut, duration, onUpdate: (o) => { callback(o.v); return ''; }, onComplete: () => { complete && complete(); return ''; }, }); } else { animate({ from: { lng: startValue.lng, lat: startValue.lat, pitch: startValue.pitch, rotation: startValue.rotation, zoom: startValue.zoom, }, to: { lng: endValue.lng, lat: endValue.lat, pitch: endValue.pitch, rotation: endValue.rotation, zoom: endValue.zoom, }, ease: easeInOut, duration, onUpdate: (o) => { callback(o); return ''; }, onComplete: () => { complete && complete(); return ''; }, }); } return ''; } const raycaster = new THREE.Raycaster(); const lng = 120.1; const lat = 30.265; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [lng, lat], pitch: 70, rotation: 220, zoom: 16, }), }); scene.on('loaded', () => { const mouse = new THREE.Vector2(); let zspace, aspace, ASpaceTextMesh, ZSpaceTextMesh; scene.registerRenderService(ThreeRender); const center = scene.getCenter(); const threeJSLayer = new ThreeLayer({ enableMultiPassRenderer: false, // @ts-ignore onAddMeshes: (threeScene, layer) => { threeScene.add(new THREE.AmbientLight(0xffffff)); const sunlight = new THREE.DirectionalLight(0xffffff, 0.25); sunlight.position.set(0, 80000000, 100000000); sunlight.matrixWorldNeedsUpdate = true; threeScene.add(sunlight); // map // https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ // height // https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ const image = new Image(); image.crossOrigin = ''; image.src = 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ'; image.onload = () => { const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0, image.width, image.height); const heightData = ctx.getImageData(0, 0, image.width, image.height).data; const s = 53000; const geometry = new THREE.PlaneGeometry(s, s, 255, 255); geometry.vertices.map((v, i) => { const r = heightData[i * 4]; const g = heightData[i * 4 + 1]; const b = heightData[i * 4 + 2]; let h = -10000.0 + (r * 255.0 * 256.0 * 256.0 + g * 255.0 * 256.0 + b * 255.0) * 0.1; h = h / 20 - 127600; h = Math.max(0, h); v.z = h; return ''; }); const material = new THREE.MeshPhongMaterial({ transparent: true, // opacity: 0.6, map: new THREE.TextureLoader().load( 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ', ), side: THREE.DoubleSide, }); const plane = new THREE.Mesh(geometry, material); layer.setObjectLngLat(plane, [120.1008, 30.2573], 0); plane.position.z = 10; threeScene.add(plane); return ''; }; // 使用 Three.js glTFLoader 加载模型 const loader = new GLTFLoader(); loader.load( 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf', (gltf) => { const antModel = gltf.scene; setDouble(antModel); // antModel.children[0].material.side = THREE.DoubleSide layer.adjustMeshToMap(antModel); layer.setMeshScale(antModel, 20, 20, 20); layer.setObjectLngLat(antModel, [center.lng - 0.002, center.lat], 0); const animations = gltf.animations; if (animations && animations.length) { const mixer = new THREE.AnimationMixer(antModel); const animation = animations[1]; const action = mixer.clipAction(animation); action.play(); layer.addAnimateMixer(mixer); } antModel.rotation.y = Math.PI; // 向场景中添加模型 threeScene.add(antModel); // 重绘图层 layer.render(); return ''; }, ); const v = ` varying vec2 vUv; varying vec4 worldPosition; void main() { vUv = uv; worldPosition = modelMatrix * vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`; const f = ` varying vec2 vUv; varying vec4 worldPosition; uniform vec3 color; void main() { gl_FragColor = vec4(color, fract(worldPosition.z / 50.0)); }`; const shadermaterial = new THREE.ShaderMaterial({ uniforms: { color: { value: new THREE.Vector3(0.21372549, 0.34705882, 0.56470588), }, }, vertexShader: v, fragmentShader: f, side: THREE.DoubleSide, }); const fbxLoaded = new FBXLoader(); // load ZSpace fbxLoaded.load( 'https://gw.alipayobjects.com/os/bmw-prod/af1652c9-3c4f-4e73-ac4c-1f78fefbaf6a.fbx', (gltf) => { zspace = gltf; layer.adjustMeshToMap(zspace); // @ts-ignore zspace.children[0].material = shadermaterial; layer.setMeshScale(zspace, 10, 10, 10); layer.setObjectLngLat(zspace, [120.1015, 30.2661], 0); zspace.rotation.x = Math.PI * 2; zspace.rotation.z = -Math.PI * (-2 / 15); threeScene.add(zspace); return ''; }, ); fbxLoaded.load( 'https://gw.alipayobjects.com/os/bmw-prod/11d6e4c1-bd5b-4dc1-bae5-ac51c14e9056.fbx', (model) => { aspace = model; layer.adjustMeshToMap(aspace); // @ts-ignore aspace.children[0].material = shadermaterial; layer.setMeshScale(aspace, 8, 8, 8); layer.setObjectLngLat(aspace, [120.099, 30.261], 0); aspace.rotation.x = Math.PI * 2; aspace.rotation.z = -Math.PI * (3 / 15); threeScene.add(aspace); return ''; }, ); console.log(THREE.FontLoader); const textLoader = new THREE.FontLoader(); textLoader.load( 'https://gw.alipayobjects.com/os/bmw-prod/0a3f46eb-294e-4d95-87f2-052c26ad4bf1.json', (font) => { const fontOptions = { size: 360, // 字号大小,一般为大写字母的高度 height: 50, // 文字的厚度 font, // 字体,默认是'helvetiker',需对应引用的字体文件 bevelThickness: 10, // 倒角厚度 bevelSize: 10, // 倒角宽度 curveSegments: 30, // 弧线分段数,使得文字的曲线更加光滑 bevelEnabled: true, // 布尔值,是否使用倒角,意为在边缘处斜切 }; const aspaceGeo = new THREE.TextGeometry('ASpace', fontOptions); aspaceGeo.center(); const zspaceGeo = new THREE.TextGeometry('ZSpace', fontOptions); zspaceGeo.center(); const fontMat = new THREE.MeshPhongMaterial({ color: 0xcccccc, shininess: 60, specular: 0xcccccc, side: THREE.DoubleSide, }); const testHeight = 900; ASpaceTextMesh = new THREE.Mesh(aspaceGeo, fontMat); ASpaceTextMesh.rotation.x = Math.PI / 2; ASpaceTextMesh.rotation.y = (-Math.PI * 3) / 4; layer.setObjectLngLat(ASpaceTextMesh, [120.099, 30.261], testHeight); threeScene.add(ASpaceTextMesh); ZSpaceTextMesh = new THREE.Mesh(zspaceGeo, fontMat); ZSpaceTextMesh.rotation.x = Math.PI / 2; ZSpaceTextMesh.rotation.y = (-Math.PI * 3) / 4; layer.setObjectLngLat(ZSpaceTextMesh, [120.103, 30.2661], testHeight); threeScene.add(ZSpaceTextMesh); getH(0, 200); function getH(h1, h2) { changeValue( h1, h2, 1000, (h) => { ASpaceTextMesh.position.z = testHeight + h; ZSpaceTextMesh.position.z = testHeight + h; return ''; }, () => { setTimeout(() => getH(h2, h1), 10); return ''; }, ); } return ''; }, ); }, }).animate(true); scene.addLayer(threeJSLayer); // @ts-ignore let currentCamera = threeJSLayer.threeRenderService?.getRenderCamera(); const currentView = { lng: center.lng, lat: center.lat, pitch: 70, rotation: 220, zoom: 16, }; scene.on('zoom', () => { const cen = scene.getCenter(); currentView.lng = cen.lng; currentView.lat = cen.lat; currentView.pitch = scene.getPitch(); currentView.zoom = scene.getZoom(); return ''; }); scene.map.on('mapchange', () => { // @ts-ignore currentCamera = threeJSLayer.getRenderCamera(); currentView.pitch = scene.getPitch(); return ''; }); const ASpaceView = { lng: 120.109509, lat: 30.251529, pitch: 83, rotation: 225, zoom: 15, }; const ZSpaceView = { lng: 120.112026, lat: 30.256881, pitch: 80, rotation: 220, zoom: 15, }; scene.on('click', (ev) => { // @ts-ignore const size = scene?.map?.getSize(); mouse.x = (ev.pixel.x / size.width) * 2 - 1; mouse.y = -(ev.pixel.y / size.height) * 2 + 1; raycaster.setFromCamera(mouse, currentCamera); const intersects = raycaster.intersectObjects([zspace, aspace], true); if (intersects.length > 0) { const object = intersects[0].object; if (object.name === 'Z空间') { selectSpace(currentView, ZSpaceView, ZSpaceTextMesh); } else { selectSpace(currentView, ASpaceView, ASpaceTextMesh); } } return ''; }); function selectSpace(currentView, targetView, spaceText) { if (spaceText) { changeValue(spaceText.rotation.y, spaceText.rotation.y + Math.PI * 2, 500, (r) => { spaceText.rotation.y = r; return ''; }); } changeValue(currentView, targetView, 500, (view) => { scene.setCenter([view.lng, view.lat]); scene.setPitch(view.pitch); scene.setRotation(view.rotation); scene.setZoom(view.zoom); currentView.lng = view.lng; currentView.lat = view.lat; currentView.pitch = view.pitch; currentView.rotation = view.rotation; currentView.zoom = view.zoom; return ''; }); } return ''; }); function setDouble(object) { if (object.children && object.children.length && object.children.length > 0) { object.children.map((child) => setDouble(child)); } else if (object.material) { object.material.side = THREE.DoubleSide; } } ``` ### 3D底图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/animate/3d-base-map/ - Source path: examples/gallery/animate/demo/3d-base-map.js ```js /* eslint-disable no-undef */ import { LineLayer, Marker, PointLayer, PolygonLayer, Scene } from '@antv/l7'; import { Map } from '@antv/l7-maps'; const pointData = [ { data: [113.177855, 23.068432], longitude: '113.177855', latitude: '23.068432', to_longitude: '108.484899', to_latitude: '22.826101', text: '广州', color: 'rgb(57,255,20)', value: '1', unit: '天', }, { data: [108.484899, 22.826101], longitude: '108.484899', latitude: '22.826101', to_longitude: '106.467366', to_latitude: '26.64921', text: '南宁', color: 'rgb(57,255,20)', value: '6', unit: '小时', }, { data: [106.467366, 26.64921], longitude: '106.467366', latitude: '26.64921', text: '贵阳', color: 'rgb(57,255,20)', value: '3', unit: '小时', }, { data: [106.563516, 29.618267], longitude: '106.563516', latitude: '29.618267', text: '重庆', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [125.403053, 43.907546], longitude: '125.403053', latitude: '43.907546', text: '长春', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [113.607498, 34.794084], longitude: '113.607498', latitude: '34.794084', to_longitude: '125.403053', to_latitude: '43.907546', text: '郑州', color: 'rgb(57,255,20)', value: '1', unit: '天', }, { data: [114.63332, 38.174659], longitude: '114.63332', latitude: ' 38.174659', text: '石家庄', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [101.740747, 36.558335], longitude: '101.740747', latitude: '36.558335', text: '西宁', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [111.677604, 40.853815], longitude: '111.677604', latitude: '40.853815', to_longitude: '106.563516', to_latitude: '29.618267', text: '呼和浩特', color: 'rgb(255,255,255)', value: '1', unit: '天', }, { data: [120.152667, 30.195612], longitude: '120.152667', latitude: '30.195612', text: '杭州', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [115.804205, 28.766485], longitude: '115.804205', latitude: '28.766485', to_longitude: '120.152667', to_latitude: '30.195612', text: '南昌', color: 'rgb(255,255,255)', value: '1', unit: '天', }, { data: [126.520858, 45.842367], longitude: '126.520858', latitude: '45.842367', text: '哈尔滨', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [123.459186, 41.711976], longitude: '123.459186', latitude: '41.711976', to_longitude: '126.520858', to_latitude: '45.842367', text: '沈阳', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, { data: [117.113981, 36.624459], longitude: '117.113981', latitude: '36.624459', to_longitude: '114.63332', to_latitude: '38.174659', text: '济南', color: 'rgb(255,255,255)', value: '3', unit: '小时', }, ]; const source = new District.RDBSource({ version: 2023, }); const scene = new Scene({ id: 'map', map: new Map({ center: [111.4453125, 32.84267363195431], pitch: 35, zoom: 3, }), }); scene.addImage( '00', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PPo0QYHNResAAAAAAAAAAAAADmJ7AQ/original', ); scene.addImage( '01', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*epXiTZ8B1McAAAAAAAAAAAAADmJ7AQ/original', ); scene.addImage( '02', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*6WGaQKkJppIAAAAAAAAAAAAADmJ7AQ/original', ); scene.setBgColor('#131722'); scene.on('loaded', () => { const map = document.getElementById('map'); map.style.background = '#131722'; for (let i = 0; i < pointData.length; i++) { const el = document.createElement('label'); el.className = 'labelclass'; el.textContent = pointData[i].value + pointData[i].unit; el.style.background = '#e24c4c8c'; el.style.borderRadius = '50%'; // 圆角半径设为半个宽度/高度,形成圆形 el.style.width = '40px'; el.style.height = '40px'; el.style.borderColor = '#e24c4c8c'; el.style.textAlign = 'center'; el.style.lineHeight = '40px'; el.style.color = '#fff'; const marker = new Marker({ element: el, offsets: [50, 10], }).setLnglat({ lng: Number(pointData[i].longitude) * 1, lat: Number(pointData[i].latitude), }); scene.addMarker(marker); } source .getData({ level: 'province', precision: 'low', }) .then((data) => { const newFeatures = data.features.filter((item) => { return item.properties.name; }); const newData = { type: 'FeatureCollection', features: newFeatures, }; // 省份边界 const lineDown = new LineLayer({ zIndex: 10, }) .source(newData) .shape('line') .color('#989494') .size(0.6) .style({ raisingHeight: 650000, opacity: 0.8, }); scene.addLayer(lineDown); return ''; }); source .getData({ level: 'country', precision: 'low', }) .then((data) => { // 中国地图填充面 const provincelayer = new PolygonLayer({ autoFit: true, }) .source(data) .size(650000) .shape('extrude') .color('#5886CF') .style({ heightfixed: true, pickLight: true, opacity: 0.8, }); // 国界线 九段线 const boundaryLine = new LineLayer({ zIndex: 10 }) .source(data) .shape('line') .color('#5DDDFF') .size(1) .style({ raisingHeight: 650000, }); scene.addLayer(boundaryLine); scene.addLayer(provincelayer); return ''; }); const flyLine3 = new LineLayer({ blend: 'normal', }) .source(pointData, { parser: { type: 'json', x: 'longitude', y: 'latitude', x1: 'to_longitude', y1: 'to_latitude', }, }) .size(2) .shape('arc3d') .color('rgb(0, 191, 255)') .animate({ interval: 0.1, trailLength: 0.4, duration: 0.5, }) .style({ sourceColor: 'rgb(0, 191, 255)', targetColor: 'rgb(57,255,20)', thetaOffset: 1, opacity: 1, }); const pointLayer = new PointLayer({ depth: false, zIndex: 11, heightFixed: true, }) .source(pointData, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('cylinder') .size([4, 4, 90]) .active(true) .color('color') .style({ opacity: 1, opacityLinear: { enable: true, // true - false dir: 'up', // up - down }, lightEnable: false, }); const pointLayer2 = new PointLayer({ zIndex: 10 }) .source(pointData, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('circle') .active(true) .animate(true) .size(40) .color('color'); const textLayer = new PointLayer({ zIndex: 2 }) .source(pointData, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('text', 'text') .size(14) .color('#0ff') .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left spacing: 2, // 字符间距 padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#0ff', // 描边颜色 strokeWidth: 0.2, // 描边宽度 raisingHeight: 2551000, textAllowOverlap: true, heightFixed: true, }); const imageLayer = new PointLayer({ zIndex: 15 }) .source(pointData, { parser: { type: 'json', x: 'longitude', y: 'latitude', }, }) .shape('text', ['00', '01', '02']) .size(10) .style({ raisingHeight: 110, }); scene.addLayer(textLayer); scene.addLayer(imageLayer); scene.addLayer(pointLayer); scene.addLayer(pointLayer2); scene.addLayer(flyLine3); return ''; }); ``` ### 路径贴图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/animate/animate-path-texture/ - Source path: examples/gallery/animate/demo/animate-path-texture.js ```js import { LineLayer, PolygonLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [120.15, 30.246], zoom: 13.5, style: 'dark', pitchEnable: false, rotation: -90, }), }); scene.on('loaded', () => { scene.addImage( 'arrow', 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', ); fetch('https://gw.alipayobjects.com/os/bmw-prod/67130c6c-7f49-4680-915c-54e69730861d.json') .then((data) => data.json()) .then(({ lakeBorderData, lakeData, landData }) => { const lakeLayer = new PolygonLayer() .source(lakeData) .shape('fill') .color('#1E90FF') .style({ opacity: 0.4, opacityLinear: { enable: true, dir: 'out', // in - out }, }); const landLayer = new PolygonLayer() .source(landData) .shape('fill') .color('#3CB371') .style({ opacity: 0.4, opacityLinear: { enable: true, dir: 'in', // in - out }, }); const lakeBorderLayer = new PolygonLayer() .source(lakeBorderData) .shape('fill') .color('#ccc') .style({ opacity: 0.5, opacityLinear: { enable: true, dir: 'in', // in - out }, }); scene.addLayer(lakeLayer); scene.addLayer(lakeBorderLayer); scene.addLayer(landLayer); }); fetch('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({}) .source(data) .size(3) .shape('line') .texture('arrow') .color('rgb(22,119,255)') .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ opacity: 0.6, lineTexture: true, // 开启线的贴图功能 iconStep: 10, // 设置贴图纹理的间距 borderWidth: 0.4, // 默认文 0,最大有效值为 0.5 borderColor: '#fff', // 默认为 #ccc }); scene.addLayer(layer); }); }); ``` ### 圆形扫光城市 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/animate/build-sweep/ - Source path: examples/gallery/animate/demo/build-sweep.js ```js import { CityBuildingLayer, LineLayer, PolygonLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', center: [120.145, 30.238915], pitch: 60, zoom: 13.2, }), }); fetch('https://gw.alipayobjects.com/os/rmsportal/ggFwDClGjjvpSMBIrcEx.json').then(async (res) => { const pointLayer = new CityBuildingLayer(); pointLayer .source(await res.json()) .size('floor', [0, 500]) .color('rgba(242,246,250,1.0)') .animate({ enable: true, }) .active({ color: '#0ff', mix: 0.5, }) .style({ opacity: 0.7, baseColor: 'rgb(16, 16, 16)', windowColor: 'rgb(30, 60, 89)', brightColor: 'rgb(255, 176, 38)', sweep: { enable: true, sweepRadius: 2, sweepColor: '#1990FF', sweepSpeed: 0.5, sweepCenter: [120.145319, 30.238915], }, }); scene.addLayer(pointLayer); }); fetch('https://gw.alipayobjects.com/os/bmw-prod/67130c6c-7f49-4680-915c-54e69730861d.json') .then((data) => data.json()) .then(({ lakeBorderData, lakeData, landData }) => { const lakeLayer = new PolygonLayer() .source(lakeData) .shape('fill') .color('#1E90FF') .style({ opacity: 0.4, opacityLinear: { enable: true, dir: 'out', // in - out }, }); const landLayer = new PolygonLayer() .source(landData) .shape('fill') .color('#3CB371') .style({ opacity: 0.4, opacityLinear: { enable: true, dir: 'in', // in - out }, }); const lakeBorderLayer = new PolygonLayer() .source(lakeBorderData) .shape('fill') .color('#ccc') .style({ opacity: 0.5, opacityLinear: { enable: true, dir: 'in', // in - out }, }); scene.addLayer(lakeLayer); scene.addLayer(lakeBorderLayer); scene.addLayer(landLayer); }); fetch('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({ zIndex: 0, depth: true, }) .source(data) .size(1) .shape('line') .color('#1990FF') .animate({ interval: 1, // 间隔 duration: 2, // 持续时间,延时 trailLength: 2, // 流线长度 }); scene.addLayer(layer); }); ``` ### 网格地图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/animate/grid/ - Source path: examples/gallery/animate/demo/grid.js ```js import { LineLayer, PointLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import { ThreeLayer, ThreeRender } from '@antv/l7-three'; import * as THREE from 'three'; function getImageData(img) { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const { width, height } = img; canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); const imageData = ctx.getImageData(0, 0, width, height); return imageData; } function getLatData(data) { const size = Math.floor(Math.sqrt(data.length)); const arr = []; const startLng = 110, lngStep = 5 / (size - 1); const startLat = 30, latStep = -5 / (size - 1); for (let i = 0; i < size; i++) { const arr2 = []; for (let j = 0; j < size; j++) { const index = i + j * size; const x = startLng + lngStep * i; const y = startLat + latStep * j; arr2.push([x, y, data[index]]); } arr.push(arr2); } return arr; } function getLngData(data) { const size = Math.floor(Math.sqrt(data.length)); const arr = []; const startLng = 110, lngStep = 5 / (size - 1); const startLat = 30, latStep = -5 / (size - 1); for (let i = 0; i < size; i++) { const arr2 = []; for (let j = 0; j < size; j++) { const index = i * size + j; const x = startLng + lngStep * j; const y = startLat + latStep * i; arr2.push([x, y, data[index]]); } arr.push(arr2); } return arr; } function getR(data) { const arr = []; for (let i = 0; i < data.length; i += 4) { arr.push(data[i]); } return arr; } function setMaterial(object) { if (object.children && object.children.length && object.children.length > 0) { object.children.map((child) => setMaterial(child)); } else if (object.material) { object.material.wireframe = true; object.material.opacity = 0.6; } } const airPorts = [ { name: '常德桃花源机场', lng: 111.641101, lat: 28.91165, }, { name: '芷江机场', lng: 109.709699, lat: 27.442172, }, { name: '铜仁凤凰机场', lng: 109.313971, lat: 27.880629, }, { name: '永州零陵机场', lng: 111.616049, lat: 26.335053, }, { name: '桂林两江国际机场', lng: 110.049256, lat: 25.210065, }, { name: '长沙黄花国际机场', lng: 113.216412, lat: 28.183613, }, { name: '井冈山机场', lng: 114.745845, lat: 26.852646, }, ]; const planeTarget = { lng2: 111.616049, lat2: 26.335053, }; const airLineData = [ { name: '常德桃花源机场', lng: 111.641101, lat: 28.91165, ...planeTarget, }, { name: '芷江机场', lng: 109.709699, lat: 27.442172, ...planeTarget, }, { name: '铜仁凤凰机场', lng: 109.313971, lat: 27.880629, ...planeTarget, }, { name: '桂林两江国际机场', lng: 110.049256, lat: 25.210065, ...planeTarget, }, { name: '长沙黄花国际机场', lng: 113.216412, lat: 28.183613, ...planeTarget, }, { name: '井冈山机场', lng: 114.745845, lat: 26.852646, ...planeTarget, }, ]; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [113, 29], pitch: 70, zoom: 7.5, rotation: 170, style: 'blank', }), }); scene.setBgColor('#000'); scene.registerRenderService(ThreeRender); const threeJSLayer = new ThreeLayer({ enableMultiPassRenderer: false, // @ts-ignore onAddMeshes: (threeScene, layer) => { threeScene.add(new THREE.AmbientLight(0xffffff)); const sunlight = new THREE.DirectionalLight(0xffffff, 0.25); sunlight.position.set(0, 800000, 1000000); sunlight.matrixWorldNeedsUpdate = true; threeScene.add(sunlight); // 使用 Three.js glTFLoader 加载模型 const loader = new window.GLTFLoader(); loader.load( 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf', (gltf) => { const antModel = gltf.scene; setMaterial(antModel); layer.adjustMeshToMap(antModel); layer.setMeshScale(antModel, 2000, 2000, 2000); layer.setObjectLngLat(antModel, [113, 29], 0); const animations = gltf.animations; if (animations && animations.length) { const mixer = new THREE.AnimationMixer(antModel); const animation = animations[1]; const action = mixer.clipAction(animation); action.timeScale = 1; action.play(); layer.addAnimateMixer(mixer); } antModel.rotation.y = Math.PI; threeScene.add(antModel); layer.render(); return ''; }, ); }, zIndex: 1, }); scene.addImage( 'plane', 'https://gw.alipayobjects.com/zos/bmw-prod/96327aa6-7fc5-4b5b-b1d8-65771e05afd8.svg', ); const airPrtsLayer = new PointLayer() .source(airPorts, { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .shape('name', 'text') .color('rgb(22,119,255)') .size(10); const airLineLayer = new LineLayer({ blend: 'normal' }) .source(airLineData, { parser: { type: 'json', x: 'lng', y: 'lat', x1: 'lng2', y1: 'lat2', }, }) .shape('arc3d') .size(1) .color('#f00') .style({ sourceColor: 'rgb(22,119,255)', targetColor: 'rgba(242,246,250,0.1)', }); const airPlaneLayer = new LineLayer({ blend: 'normal', zIndex: 1 }) .source(airLineData, { parser: { type: 'json', x: 'lng2', y: 'lat2', x1: 'lng', y1: 'lat', }, }) .shape('arc3d') .texture('plane') .size(30) .color('#f00') .animate({ duration: 0.2, interval: 0.2, trailLength: 0.2, }) .style({ textureBlend: 'replace', lineTexture: true, // 开启线的贴图功能 iconStep: 6, // 设置贴图纹理的间距 }); fetch('https://gw.alipayobjects.com/os/bmw-prod/ec5351c9-d22b-4918-ad6c-1838064d3a64.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({}).source(data).size(10000).shape('wall').style({ opacity: 0.4, sourceColor: '#0DCCFF', targetColor: 'rbga(255,255,255, 0)', heightfixed: true, }); scene.addLayer(layer); const nameLayer = new PointLayer({ zIndex: 3 }) .source(data) .color('rgb(22,119,255)') .size(15) .shape('name', 'text'); scene.addLayer(nameLayer); }); const img = new Image(); img.crossOrigin = 'none'; img.src = 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*UkvYRYS5jTAAAAAAAAAAAAAAARQnAQ'; img.onload = function () { const data = getImageData(img); const rData = getR(data.data); const d1 = getLngData(rData); const d2 = getLatData(rData); const geoData = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'MultiLineString', coordinates: d1, }, }, { type: 'Feature', properties: {}, geometry: { type: 'MultiLineString', coordinates: d2, }, }, ], }; const layer = new LineLayer({}) .source(geoData) .size(1) .shape('simple') .color('rgb(22, 119, 255)') .style({ vertexHeightScale: 2000, opacity: 0.4, }); scene.addLayer(layer); }; const pointData = [ { lng: 113, lat: 29, size: 10000 }, { lng: 113.5, lat: 29.5, size: 30000 }, { lng: 110.23681640625, lat: 29.64509464986076, size: 74020.50373907911 }, { lng: 115.01586914062499, lat: 26.88777988202911, size: 22908.885529976185 }, { lng: 111.181640625, lat: 28.724313406473463, size: 73359.37302978932 }, { lng: 112.686767578125, lat: 29.257648503615542, size: 18500.90838085843 }, { lng: 114.664306640625, lat: 28.98892237190413, size: 20293.183968726793 }, { lng: 113.90075683593749, lat: 28.17855984939698, size: 18051.412077639496 }, { lng: 111.51123046875, lat: 27.45466493898314, size: 37645.94186119526 }, { lng: 110.67626953125, lat: 28.004101830368654, size: 4214.588023703825 }, { lng: 114.43359375, lat: 29.477861195816843, size: 61722.01580332115 }, { lng: 110.445556640625, lat: 26.96124577052697, size: 70806.75519747598 }, { lng: 113.75244140624999, lat: 27.88278388425912, size: 70930.24993464859 }, ]; const waveLayer = new PointLayer({ zIndex: 2, blend: 'additive' }) .source(pointData, { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .shape('circle') .color('rgb(22, 119, 255)') .size('size', (v) => v) .animate(true) .style({ unit: 'meter', }); const barLayer = new PointLayer({ zIndex: 2, depth: false }) .source(pointData, { parser: { type: 'json', x: 'lng', y: 'lat', }, }) .shape('cylinder') .color('rgb(22, 119, 255)') .size('size', (v) => [5, 5, v / 350]) .animate(true) .style({ opacityLinear: { enable: true, dir: 'up', }, lightEnable: false, }); scene.on('loaded', () => { scene.addLayer(waveLayer); scene.addLayer(barLayer); scene.addLayer(threeJSLayer); scene.addLayer(airPrtsLayer); scene.addLayer(airLineLayer); scene.addLayer(airPlaneLayer); }); ``` ### 都灵道路图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/animate/turin/ - Source path: examples/gallery/animate/demo/turin.js ```js import { LineLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [7.65, 45.053], zoom: 12, style: 'dark', }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/bmw-prod/98a5d9ec-be97-44bd-bff0-5742d929c003.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({}) .source(data) .shape('line') .color('highway', (v) => { switch (v) { case 'motorway': return '#F9D371'; case 'motorway_link': return '#3DB2FF'; case 'trunk': return 'green'; case 'trunk_link': return '#6E85B2'; case 'primary': return '#F47340'; case 'primary_link': return '#F6A9A9'; case 'secondary': return '#EF2F88'; case 'secondary_link': return '#5F7A61'; case 'tertiary': return '#1ee3cf'; case 'tertiary_link': return '#C2F784'; case 'pedestrian': return '#FFF89A'; case 'residential': return 'rgba(22, 119, 255, .5)'; case 'road': return '#93FFD8'; case 'path': return '#BAFFB4'; case 'unclassified': return '#D3DEDC'; case 'service': return '#AEFEFF'; case 'living_street': return '#9B0000'; case 'track': return '#F5F5F5'; case 'highway': return 'red'; case 'rail': return '#08ffc8'; default: return '#FFE3E3'; } }) .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }); scene.addLayer(layer); }); }); ``` ### 弧线地图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/arc-circle/ - Source path: examples/gallery/basic/demo/arc-circle.js ```js import { LineLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', center: [107.77791556935472, 35.443286920228644], zoom: 2.9142882493605033, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt') .then((res) => res.text()) .then((data) => { const layer = new LineLayer({ blend: 'additive', }) .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); }); }); ``` ### 公交线路深色 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/bus-dark/ - Source path: examples/gallery/basic/demo/bus-dark.js ```js import { LineLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', center: [103.83735604457024, 1.360253881403068], pitch: 4.00000000000001, zoom: 10.210275860702593, rotation: 19.313180925794313, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/ee07641d-5490-4768-9826-25862e8019e1.json') .then((res) => res.json()) .then((data) => { const layer = new LineLayer({}) .source(data, { parser: { coordinates: 'path', type: 'json', }, }) .size('level', (level) => { return [1.0, level * 1]; }) .shape('line') .color( 'level', [ '#312B60', '#4A457E', '#615C99', '#816CAD', '#A67FB5', '#C997C7', '#DEB8D4', '#F5D4E6', '#FAE4F1', '#FFF3FC', ].slice(0, 8), ); scene.addLayer(layer); }); }); ``` ### 3D柱图深色 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/column-dark/ - Source path: examples/gallery/basic/demo/column-dark.js ```js import { PointLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ pitch: 35.210526315789465, style: 'dark', center: [104.288144, 31.239692], zoom: 4.4, }), }); console.log('111'); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json') .then((res) => res.json()) .then((data) => { const pointLayer = new PointLayer({}) .source(data.list, { parser: { type: 'json', x: 'j', y: 'w', }, }) .shape('cylinder') .size('t', function (level) { return [2, 2, level * 2 + 20]; }) .animate(true) .active(true) .color('t', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#CEF8D6', ]); scene.addLayer(pointLayer); }); }); ``` ### 蜂窝图3D - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/light/ - Source path: examples/gallery/basic/demo/light.js ```js import { HeatmapLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'dark', pitch: 43, center: [120.13383079335335, 29.651873105004427], zoom: 7.068989519212174, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/basement_prod/a1a8158d-6fe3-424b-8e50-694ccf61c4d7.csv') .then((res) => res.text()) .then((data) => { const layer = new HeatmapLayer({}) .source(data, { parser: { type: 'csv', x: 'lng', y: 'lat', }, transforms: [ { type: 'hexagon', size: 2500, field: 'v', method: 'sum', }, ], }) .size('sum', (sum) => { return sum * 100; }) .shape('hexagonColumn') .style({ coverage: 0.8, angle: 0, }) .color('sum', [ '#094D4A', '#146968', '#1D7F7E', '#289899', '#34B6B7', '#4AC5AF', '#5FD3A6', '#7BE39E', '#A1EDB8', '#C3F9CC', '#DEFAC0', '#ECFFB1', ]); scene.addLayer(layer); }); }); ``` ### 亮度图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/normal/ - Source path: examples/gallery/basic/demo/normal.js ```js import { PointLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ center: [121.417463, 31.215175], style: 'dark', zoom: 11, }), }); scene.on('loaded', () => { fetch('https://gw.alipayobjects.com/os/rmsportal/BElVQFEFvpAKzddxFZxJ.txt') .then((res) => res.text()) .then((data) => { const pointLayer = new PointLayer({ blend: 'additive', }) .source(data, { parser: { type: 'csv', y: 'lat', x: 'lng', }, }) .size(0.5) .color('#080298'); scene.addLayer(pointLayer); }); }); ``` ### 福建省地图 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/province-map/ - Source path: examples/gallery/basic/demo/province-map.ts ```ts import { PointLayer, PolygonLayer, Scene } from '@antv/l7'; import { Map } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new Map({ pitch: 0, style: 'light', center: [118, 24.8], zoom: 6, }), }); scene.on('loaded', async () => { scene.addImage( 'province', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hvqeQa9I6ccAAAAAAAAAAAAADmJ7AQ/original', ); scene.addImage( 'city', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sBlgRp8Ah7sAAAAAAAAAAAAADmJ7AQ/original', ); scene.addImage( 'county', 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ufrWTqCNCScAAAAAAAAAAAAADmJ7AQ/original', ); // 获取数据 const dataList = [ // 市级行政区 'https://mdn.alipayobjects.com/afts/file/A*jPjCTad_s24AAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA.json', // 市级行政区一级群列岛名 'https://mdn.alipayobjects.com/afts/file/A*HW8yQb2joA8AAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E4%B8%80%E7%BA%A7%E7%BE%A4%E5%88%97%E5%B2%9B%E5%90%8D.json', ///市级行政区一级河流名.json 'https://mdn.alipayobjects.com/afts/file/A*EjtNRrENGToAAAAAAAAAAAAADrd2AQ/市级行政区一级河流名.json', //市级行政区一级港湾名.json 'https://mdn.alipayobjects.com/afts/file/A*lqxATobbMLwAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E4%B8%80%E7%BA%A7%E6%B8%AF%E6%B9%BE%E5%90%8D.json', //市级行政区一级岛屿名.json 'https://mdn.alipayobjects.com/afts/file/A*xyeHRZCF8DsAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E4%B8%80%E7%BA%A7%E5%B2%9B%E5%B1%BF%E5%90%8D.json', //市级行政区县级行政中心.json 'https://mdn.alipayobjects.com/afts/file/A*vrDfSrB8J4sAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%8E%BF%E7%BA%A7%E8%A1%8C%E6%94%BF%E4%B8%AD%E5%BF%83.json', //市级行政区县级行政区.json 'https://mdn.alipayobjects.com/afts/file/A*lfffQ5ej7AEAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%8E%BF%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA.json', // 市级行政区省级行政中心.json 'https://mdn.alipayobjects.com/afts/file/A*jtlsTqxTJkoAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E7%9C%81%E7%BA%A7%E8%A1%8C%E6%94%BF%E4%B8%AD%E5%BF%83.json', //市级行政区山峰.json 'https://mdn.alipayobjects.com/afts/file/A*DRSfRqBs9qsAAAAAAAAAAAAADrd2AQ/市级行政区山峰.json', //市级行政区色带.json 'https://mdn.alipayobjects.com/afts/file/A*KRD4QbjkZCMAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E8%89%B2%E5%B8%A6.json', //市级行政区面状水域.json 'https://mdn.alipayobjects.com/afts/file/A*3e9nSJwXqu0AAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E9%9D%A2%E7%8A%B6%E6%B0%B4%E5%9F%9F.json', //市级行政区境界线.json 'https://mdn.alipayobjects.com/afts/file/A*tA8nSqhulQQAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%A2%83%E7%95%8C%E7%BA%BF.json', //市级行政区河流.json 'https://mdn.alipayobjects.com/afts/file/A*2vGmRrYpTjEAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E6%B2%B3%E6%B5%81.json', //市级行政区海岸线.json 'https://mdn.alipayobjects.com/afts/file/A*juI9TpBcQ74AAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E6%B5%B7%E5%B2%B8%E7%BA%BF.json', //市级行政区二级群列岛名.json 'https://mdn.alipayobjects.com/afts/file/A*E4ReSqdYq-cAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E4%BA%8C%E7%BA%A7%E7%BE%A4%E5%88%97%E5%B2%9B%E5%90%8D.json', //市级行政区地级市行政中心.json 'https://mdn.alipayobjects.com/afts/file/A*I3HSQaYyQ_UAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%9C%B0%E7%BA%A7%E5%B8%82%E8%A1%8C%E6%94%BF%E4%B8%AD%E5%BF%83.json', //市级行政区大型水库名.json 'https://mdn.alipayobjects.com/afts/file/A*xxXKTpte0VUAAAAAAAAAAAAADrd2AQ/%E5%B8%82%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%A4%A7%E5%9E%8B%E6%B0%B4%E5%BA%93%E5%90%8D.json', ]; const result = await Promise.all(dataList.map(async (url) => await (await fetch(url)).json())); const cityLayer = new PolygonLayer({ autoFit: true, }) .source(result[6]) .shape('fill') .scale('COLOR', { type: 'cat', domain: ['Y', 'P', 'G', 'R'], }) .color('COLOR', ['#f7f6c6', '#fceaea', '#e0e7d5', '#f3e4cf']); // 陆上轮廓 const layer2 = new PolygonLayer().source(result[9]).shape('fill').color('#b4cad7'); // 水域 const waterLayer = new PolygonLayer().source(result[10]).shape('fill').color('#bcebfe'); // 面状河流线 const waterLayerLine = new PolygonLayer() .source(result[10]) .shape('line') .size(0.5) .color('#50aac8'); // 线河流线 const river_Line = new PolygonLayer().source(result[12]).shape('line').size(0.5).color('#50aac8'); // 群岛标注图层 const island_name = new PointLayer({ minZoom: 8, }) .source(result[1]) .shape('NAME', 'text') .size(15) .color('#3b474e'); // 河流标注图层 const river_name = new PointLayer({ minZoom: 5 }) .source(result[2]) .shape('NAME', 'text') .size(15) .color('#4aa1bd') .style({ fontWeight: 800, }); // 港湾标注 const gangwan_name = new PointLayer({ minZoom: 6, }) .source(result[3]) .shape('NAME', 'text') .size(15) .color('#4eaed9') .style({ fontWeight: 800, }); // 群岛 const island_name1 = new PointLayer({ minZoom: 8, }) .source(result[4]) .shape('NAME', 'text') .size(15) .color('#3b474e') .style({ fontWeight: 600, }); // 县界 const county_Line = new PolygonLayer({ minZoom: 5, }) .source(result[11]) .shape('line') .size(0.3) .color('#a59f97'); // 城市界 const city_Line = new PolygonLayer().source(result[0]).shape('line').size(0.5).color('#787269'); // 海岸线 const sea_Line = new PolygonLayer().source(result[13]).shape('line').size(0.5).color('#50aac8'); // 城市标注 const cityName = new PointLayer({ maxZoom: 8, minZoom: 5, }) .source(result[15]) .shape('NAME', 'text') .size(14) .color('#000') .style({ fontWeight: 800, textAnchor: 'top', textAllowOverlap: true, textOffset: [0, 12], }); // 城市点位 const cityPoint = new PointLayer({ maxZoom: 7, minZoom: 5, }) .source(result[15]) .shape('city') .size(5); // 省级市标注 const provinceCityName = new PointLayer({ minZoom: 5, maxZoom: 7, }) .source(result[7]) .shape('NAME', 'text') .size(14) .color('#000') .style({ fontWeight: 800, textAnchor: 'top', textOffset: [0, 12], }); // 省级市点位 const provincePoint = new PointLayer({ minZoom: 5, maxZoom: 7, }) .source(result[7]) .shape('province') .size(5); // 县标注 const countyName = new PointLayer({ minZoom: 8, }) .source(result[5]) .shape('NAME', 'text') .size(14) .color('#333') .style({ fontWeight: 600, textAnchor: 'top', textOffset: [0, 12], }); 7; // 县点位 const countyPoint = new PointLayer({ minZoom: 8, }) .source(result[5]) .shape('county') .size(5); // 县标注 const mountainPoint = new PointLayer({ minZoom: 6, }) .source(result[8]) .shape('triangle') .size(6) .color('#326648'); // 山标注 const mountainPoint_name = new PointLayer({ minZoom: 6, }) .source(result[8]) .shape('NAME', 'text') .size(14) .color('#326648') .style({ fontWeight: 800, textAnchor: 'top', textOffset: [0, 12], }); scene.addLayer(cityLayer); scene.addLayer(layer2); scene.addLayer(waterLayer); scene.addLayer(waterLayerLine); scene.addLayer(river_Line); scene.addLayer(county_Line); scene.addLayer(city_Line); scene.addLayer(sea_Line); scene.addLayer(cityName); scene.addLayer(cityPoint); scene.addLayer(countyName); scene.addLayer(countyPoint); scene.addLayer(provinceCityName); scene.addLayer(provincePoint); scene.addLayer(island_name); scene.addLayer(island_name1); scene.addLayer(gangwan_name); scene.addLayer(river_name); scene.addLayer(mountainPoint); scene.addLayer(mountainPoint_name); console.log(result); }); ``` ### 卷帘对比-作物长势 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/basic/swipe/ - Source path: examples/gallery/basic/demo/swipe.ts ```ts import { Map, RasterLayer, Scene, Swipe } from '@antv/l7'; import * as GeoTIFF from 'geotiff'; const scene = new Scene({ id: 'map', map: new Map({ pitch: 0, center: [-96, 37.8], zoom: 14, }), }); async function getTiffData(url: string) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image = await tiff.getImage(); const width = image.getWidth(); const height = image.getHeight(); const values = await image.readRasters(); return { data: values[0], width, height, }; } scene.on('loaded', async () => { const colors = [ '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', ]; const ndvi1 = await getTiffData( 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/file/A*sZpWQZK21NIAAAAAAAAAAAAADmJ7AQ/ndvi2022-03-01.glb', ); const ndvi2 = await getTiffData( 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/file/A*JeHQTIzN4_kAAAAAAAAAAAAADmJ7AQ/ndvi2022-10-01.NDVI.glb', ); // 影像地图图层 const baseLayer = new RasterLayer({ zIndex: -1 }).source( 'https://www.google.com/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}', { parser: { type: 'rasterTile', tileSize: 256, zoomOffset: 0, }, }, ); const leftLayer = new RasterLayer({ autoFit: true, }) .source(ndvi1.data, { parser: { type: 'raster', width: ndvi1.width, height: ndvi1.height, extent: [-112.117293306503, 32.78212288135407, -111.77216057434428, 33.10568277278276], }, }) .style({ clampLow: false, clampHigh: false, domain: [-1, 1], nodataValue: 0, rampColors: { type: 'linear', positions: [-0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1.0], // 数据需要换成 0-1 colors: colors, }, }); const rightLayer = new RasterLayer({}) .source(ndvi2.data, { parser: { type: 'raster', width: ndvi2.width, height: ndvi2.height, extent: [-112.117293306503, 32.78212288135407, -111.77216057434428, 33.10568277278276], }, }) .style({ clampLow: false, clampHigh: false, domain: [-1, 1], nodataValue: 0, rampColors: { type: 'linear', positions: [-0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1.0], // 数据需要换成 0-1 colors: colors, }, }); scene.addLayer(baseLayer); scene.addLayer(leftLayer); scene.addLayer(rightLayer); const swipe = new Swipe({ orientation: 'vertical', ratio: 0.5, layers: [leftLayer], rightLayers: [rightLayer], }); scene.addControl(swipe); }); ``` ### 加沙 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/story/gaza/ - Source path: examples/gallery/story/demo/gaza.js ```js import { PointLayer, PolygonLayer, RasterLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [121.268, 30.3628], zoom: 10, }), }); scene.on('loaded', async () => { const googleurl = 'https://www.google.com/maps/vt?lyrs=s@820&gl=cn&x={x}&y={y}&z={z}'; const gazafill = await ( await fetch( 'https://mdn.alipayobjects.com/afts/file/A*7h8hS5hqXkcAAAAAAAAAAAAADrd2AQ/gaza.geo.json', ) ).json(); const gazacity = await ( await fetch( 'https://mdn.alipayobjects.com/afts/file/A*3xTGQ6ZeTIcAAAAAAAAAAAAADrd2AQ/gazacity.json', ) ).json(); const fillLayer = new PolygonLayer({ visible: false, }) .source(gazafill) .shape('fill') .color('red'); const googleMap = new RasterLayer({ zIndex: -1, maskLayers: [fillLayer], zoomOffset: 1, updateStrategy: 'overlap', }).source(googleurl, { parser: { type: 'rasterTile', tileSize: 256, }, }); const fillLine = new PolygonLayer({ autoFit: true, }) .source(gazafill) .shape('line') .color('red') .size(1); const cityLayer = new PointLayer() .source(gazacity) .shape('circle') .size(5) .color('#027aff') .style({ opacity: 1, stroke: '#fff', strokeWidth: 2 }); const cityLayerName = new PointLayer() .source(gazacity) .shape('city', 'text') .size(12) .color('#027aff') .style({ textAnchor: 'top', // 文本相对锚点的位置 center|left|right|top|bottom|top-left spacing: 2, // 字符间距 fontWeight: '800', textOffset: [0, 30], padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#ffffff', // 描边颜色 strokeWidth: 2, // 描边宽度 textAllowOverlap: true, }); scene.addLayer(googleMap); scene.addLayer(fillLine); scene.addLayer(fillLayer); scene.addLayer(cityLayer); scene.addLayer(cityLayerName); }); ``` ### 一带一路 - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/story/yidaiyilu/ - Source path: examples/gallery/story/demo/yidaiyilu.js ```js import { LineLayer, PointLayer, PolygonLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const scene = new Scene({ id: 'map', map: new GaodeMap({ style: 'light', center: [60.268, 30.3628], zoom: 1.5, }), }); scene.on('loaded', async () => { scene.addImage('local', 'https://gw.alipayobjects.com/zos/rmsportal/xZXhTxbglnuTmZEwqQrE.png'); const belt = await ( await fetch('https://gw.alipayobjects.com/os/rmsportal/UpapMomPYUeiBjbHNAma.json') ).json(); const line = await ( await fetch('https://gw.alipayobjects.com/os/rmsportal/kwUdcXnxQtexeGRvTGtA.json') ).json(); const line2 = await ( await fetch('https://gw.alipayobjects.com/os/rmsportal/dzpMOiLYBKxpdmsgBLoE.json') ).json(); const point = await ( await fetch('https://gw.alipayobjects.com/os/rmsportal/opYqFyDGyGUAUXkLUhBV.json') ).json(); const fillLayer = new PolygonLayer({ autoFit: false, }) .source(belt) .color('cname', function (value) { return value == '中国' ? 'rgba(46,149,169,0.45)' : 'rgba(227,244,244,1)'; }) .shape('fill'); const linelayer = new LineLayer().source(line).color('rgb(79,147,234)').size(1.5).shape('line'); const linelayer2 = new LineLayer() .source(line2) .color('rgb(11,94,69)') .size(1.5) .shape('line') .style({ // 'lineType':'solid' }); const pointlayer = new PointLayer({}).source(point).size(12.0).shape('local'); const textlayer = new PointLayer({}) .source(point) .size(12.0) .shape('name', 'text') .color('#027aff') .style({ textOffset: [0, -42], stroke: '#fff', strokeWidth: 2, textAnchor: 'bottom', }); scene.addLayer(fillLayer); scene.addLayer(linelayer); scene.addLayer(linelayer2); scene.addLayer(pointlayer); scene.addLayer(textlayer); }); ``` ### 一带一路GDP - zh page: https://l7.antv.antgroup.com/zh/examples/gallery/story/yidaiyilu2/ - Source path: examples/gallery/story/demo/yidaiyilu2.js ```js import { Control, DOM, LayerPopup, LineLayer, PolygonLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; const styleElement = document.createElement('style'); // 在
符合民政部数据规格,省、市、县三级数据,提供历史版本数据。
提供在线可视化下载、数据 SDK、数据服务和可视化组件,满足不同的数据应用需求。
提供 GeoJSON、JSON、TopoJSON、CSV、KML 多种数据下载方式,以及 SVG 格式图像下载。
Popup 示例的自定义内容