* fix: iconservice

* fix: setcenter 方法

* fix: layerpopup demo

* docs: update demo

* fix: 文档格式

* fix: popup 显示

* fix: lint error

* fix: icon 图表加载延迟不能正常渲染
This commit is contained in:
@thinkinggis 2022-11-21 01:00:06 +08:00 committed by GitHub
parent 0d2076e845
commit 536682ad4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 975 additions and 359 deletions

View File

@ -49,6 +49,7 @@ const Demo: FunctionComponent = () => {
]),
)
.color('#ffffff')
.shape('circle')
.size(10);
const polygonLayer = new PolygonLayer({
@ -76,8 +77,7 @@ const Demo: FunctionComponent = () => {
]),
)
.color('#ff0000')
.size(10)
.shape('circle');
.shape('fill');
const lineString = new LineLayer({
name: 'lineLayer',
@ -130,8 +130,18 @@ const Demo: FunctionComponent = () => {
fields: ['name'],
},
],
trigger: 'hover',
trigger: 'mousemove',
});
pointLayer.on('mousemove', (e) => {
console.log('point mousemove', e);
});
polygonLayer.on('mousemove', (e) => {
console.log('polygon mousemove', e);
});
lineString.on('mousemove', (e) => {
console.log('line mousemove', e);
});
newScene.addPopup(newPopup);
setPopup(newPopup);
setScene(newScene);

View File

@ -50,7 +50,6 @@ export default () => {
},
})
.style({
heightRatio: 100,
opacity: 0.8,
domain: [0, 2000],
rampColors: {

View File

@ -1,5 +1,5 @@
// @ts-ignore
import { PointLayer, Scene } from '@antv/l7';
import { PointLayer, Scene,Popup } from '@antv/l7';
// @ts-ignore
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
@ -37,7 +37,6 @@ export default () => {
return item;
});
const imageLayer = new PointLayer({
blend: 'normal',
})
.source(newData, {
parser: {
@ -55,8 +54,22 @@ export default () => {
imageLayer.on('mousedown', (e) => {
console.log('mousedown', e);
});
const popup = new Popup({
});
scene.addPopup(popup);
imageLayer.on('click', (e) => {
console.log('click', e);
console.log(e)
const {lng,lat} = e.lngLat
popup.setOptions({
title: e.feature.name,
html:e.feature.name,
lngLat: {
lng,
lat,
},
});
});
}, []);

View File

@ -56,7 +56,6 @@ export default () => {
},
})
.style({
heightRatio: 100,
opacity: 0.8,
domain: [0, 4000],
rampColors: {

View File

@ -119,7 +119,7 @@ export default class Popup<O extends IPopupOption = IPopupOption>
this.mapsService.on('viewchange', this.update);
this.scene = scene;
this.update();
// 临时关闭
this.updateCloseOnClick();
this.updateCloseOnEsc();
this.updateFollowCursor();
@ -216,6 +216,7 @@ export default class Popup<O extends IPopupOption = IPopupOption>
}
if (this.checkUpdateOption(option, ['lngLat']) && option.lngLat) {
this.setLnglat(option.lngLat);
this.show();
}
return this;
}
@ -459,7 +460,9 @@ export default class Popup<O extends IPopupOption = IPopupOption>
// this.closeButton.type = 'button';
closeButton.setAttribute('aria-label', 'Close popup');
closeButton.addEventListener('click', this.onCloseButtonClick);
closeButton.addEventListener('click', () => {
this.hide();
});
this.closeButton = closeButton;
} else {
@ -477,7 +480,7 @@ export default class Popup<O extends IPopupOption = IPopupOption>
if (e.stopPropagation) {
e.stopPropagation();
}
this.remove();
this.hide();
};
protected update = () => {

View File

@ -41,15 +41,14 @@ export default class IconService extends EventEmitter implements IIconService {
this.loadingImageCount++;
if (this.hasImage(id)) {
console.warn('Image Id already exists');
} else {
this.iconData.push({
id,
size: imageSize,
});
}
this.iconData.push({
id,
size: imageSize,
});
this.updateIconMap();
this.updateIconMap();// 先存储 ID
imagedata = await this.loadImage(image) as HTMLImageElement;
// imagedata = this.loadImage(image)
// imagedata = img as HTMLImageElement;
const iconImage = this.iconData.find((icon: IIcon) => {
return icon.id === id;
});
@ -61,7 +60,7 @@ export default class IconService extends EventEmitter implements IIconService {
this.update();
}
/**
*
* @param id

View File

@ -132,9 +132,8 @@ export default class FillImageModel extends BaseModel {
}
public async initModels():Promise<IModel[]> {
this.updateTexture();
this.iconService.on('imageUpdate', this.updateTexture);
this.updateTexture();
const {
unit = 'l7size',
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;

View File

@ -82,9 +82,11 @@ export default class ImageModel extends BaseModel {
}
public async initModels():Promise<IModel[]> {
this.registerBuiltinAttributes();
this.updateTexture();
this.iconService.off('imageUpdate', this.updateTexture);
this.iconService.on('imageUpdate', this.updateTexture);
// this.registerBuiltinAttributes();
this.updateTexture();
return await this.buildModels();
}
@ -173,7 +175,11 @@ export default class ImageModel extends BaseModel {
mipmap: true,
});
// 更新完纹理后在更新的图层的时候需要更新所有的图层
this.layerService.throttleRenderLayers();
// this.layer.layerModelNeedUpdate = true;
setTimeout(()=>{ // 延迟渲染
this.layerService.throttleRenderLayers();
})
return;
}
this.texture = createTexture2D({

View File

@ -289,7 +289,10 @@ export default class AMapService extends AMapBaseService {
// 在使用 map.customCoords 的时候必须使用
const mapInitCenter = map.getCenter();
// @ts-ignore
map.customCoords.setCenter([mapInitCenter.lng, mapInitCenter.lat]);
// @ts-ignore
this.map.customCoords?.setCenter([mapInitCenter.lng, mapInitCenter.lat]);
// @ts-ignore
this.setCustomCoordCenter([mapInitCenter.lng, mapInitCenter.lat]);
// 监听地图相机事件

View File

@ -122,7 +122,7 @@ export default abstract class AMapBaseService
if (MapServiceEvent.indexOf(type) !== -1) {
this.eventEmitter.off(type, handler);
} else {
this.map.on(AMapEventMap[type] || type, handler);
this.map.off(AMapEventMap[type] || type, handler);
}
}

View File

@ -301,6 +301,14 @@ export default defineConfig({
},
order: 3,
},
{
slug: 'api/component',
title: {
zh: '组件 Component',
en: 'Component',
},
order: 3,
},
{
slug: 'api/base_layer',
title: {
@ -381,14 +389,6 @@ export default defineConfig({
},
order: 11,
},
{
slug: 'api/component',
title: {
zh: '组件 Component',
en: 'Component',
},
order: 12,
},
{
slug: 'api/component/control',
title: {

View File

@ -1,6 +0,0 @@
---
title: AMap
order: 1
---
<embed src="@/docs/api/map/gaode.zh.md"></embed>

View File

@ -1,4 +0,0 @@
---
title: 高德地图
order: 1
---

View File

@ -1,6 +0,0 @@
---
title: Leaflet
order: 1
---
<embed src="@/docs/api/map/leaflet.zh.md"></embed>

View File

@ -1,4 +0,0 @@
---
title: Leaflet
order: 1
---

View File

@ -14,22 +14,42 @@ L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管
目前 L7 支持两种地图底图
- 高德地图 国内业务场景 合规中国地图
- MapBox 国际业务,或者内网离线部署场景
- Map 独立地图引擎,不需要底图、或者加载地图瓦片服务,不需要 Token
- 高德地图 国内业务场景 合规中国地图 从 2.11.0 版本起 GaodeMap 默认指向 高德 2.0 版本需要注册 Token
- MapBox 国际业务, 需要注册 oken
### import
```javascript
import { GaodeMap } from '@antv/l7-maps'; // 默认引入高德1.x
import { GaodeMapV2 } from '@antv/l7-maps'; // 默认引入高德2.0 版本
import { GaodeMap } from '@antv/l7-maps'; // 默认引入高德 2.x 版本 2.11.0 版本开始默认升级为v2
import { GaodeMapV1 } from '@antv/l7-maps'; // 2.11.0 版本之前版本默认升级为v1
import { Mapbox } from '@antv/l7-maps';
import { Map } from '@antv/l7-maps';
```
### 实例化
⚠️ 使用地图申请地图 tokenL7 内部设置了默认 token仅供测试使用
#### 默认 Map 实例化
```js
import { Map } from '@antv/l7-maps';
const scene = new Scene({
id: 'map',
map: new Map({
style: 'dark',
center: [103, 30],
pitch: 4,
zoom: 10,
rotation: 19,
}),
});
```
#### 高德地图实例化
高德地图 API 配置参数

View File

@ -1,6 +0,0 @@
---
title: Mapbox
order: 1
---
<embed src="@/docs/api/map/mapbox.zh.md"></embed>

View File

@ -1,4 +0,0 @@
---
title: Mapbox
order: 1
---

View File

@ -0,0 +1,4 @@
---
title: RasterLayer 波段计算
order: 3
---

View File

@ -32,7 +32,6 @@ const layer = new RasterLayer({})
},
})
.style({
heightRatio: 100,
opacity: 0.8,
domain: [0, 2000],
rampColors: {

View File

@ -0,0 +1,4 @@
---
title: RasterLayer 多波段计算
order: 2
---

View File

@ -0,0 +1,23 @@
---
title: RasterLayer 多波段合成
order: 1
---
<embed src="@/docs/common/style.md"></embed>
## 简介
`RasterLayer` 图层主要实现栅格数据的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图,植被分布图,夜光图。
## Option
<embed src="@/docs/common/layer/options.md"></embed>
## source
<embed src="@/docs/api/source/raster/raster_rgb.md"></embed>
## style
- opacity
透明度

View File

@ -0,0 +1,6 @@
---
title: RasterLayer single band
order: 0
---
<embed src="@/docs/api/raster_layer/raster_layer.zh.md"></embed>

View File

@ -0,0 +1,53 @@
---
title: RasterLayer 单波段
order: 0
---
<embed src="@/docs/common/style.md"></embed>
## 简介
`RasterLayer` 图层主要实现栅格数据的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图,植被分布图,夜光图。
## source
<embed src="@/docs/api/source/raster/raster_single.md"></embed>
## 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
- 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],
},
});
```

View File

@ -1,6 +0,0 @@
---
title: Scale
order: 6
---
<embed src="@/docs/api/raster_layer/scale.zh.md"></embed>

View File

@ -1,8 +0,0 @@
---
title: Scale
order: 6
---
<embed src="@/docs/common/style.md"></embed>
<embed src="@/docs/common/layer/scale.md"></embed>

View File

@ -13,100 +13,6 @@ const source = new Source(data, {
});
```
### 加载解析完的栅格数据
对栅格文件的解析,波段的提取需要用户自己完成,传入给栅格图层的是解析完成的数据。
- 在这种形式下栅格图层只能绘制单一波段的数据。
- 在这种形式下栅格图层不支持波段数据的计算。
```js
async function getTiffData() {
const response = await fetch(
'https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat',
);
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], // 使用 0 波段的数据
width,
height,
};
}
const tiffdata = await getTiffData(); // 这是解析完的数据
const layer = new RasterLayer({}).source(tiffdata.data, {
parser: {
type: 'raster',
width: tiffdata.width,
height: tiffdata.height,
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
},
});
```
#### data
<description> _IRasterData_ **必选** </description>
用户需要传入解析完的栅格数据。
```js
interface IRasterData {
data: number[][];
width: number;
height: number;
}
```
#### parser
<description> _IParser_ **必选** </description>
为使用栅格数据的使用提供必要的参数。
```js
interface IParser {
type: string;
width: number;
height: number;
extent: number[];
}
```
##### type
<description> _string_ **必选** </description>
传入固定值为 raster
##### width
<description> _number_ **必选** </description>
栅格数据是二维的网格数据,`width` 参数用于指定网格的宽度。
`width` 参数一般在使用诸如 `geotiff.js` 等库解析完成的时候会同时返回。
##### height
<description> _number_ **必选** </description>
栅格数据是二维的网格数据,`height` 参数用于指定网格的宽度。
`width` 参数一般在使用诸如 `geotiff.js` 等库解析完成的时候会同时返回。
##### extent
<description> _number[]_ **必选** </description>
`extent` 描述的是栅格数据覆盖的地理区间,数值指定的是绘制栅格的经纬度区间(左下角和右上角)。
```js
const extent = [minLng, minLat, maxLng, maxLat];
```
### 加载未解析的栅格数据
我们可以直接将请求到的栅格文件的二进制数据直接传递给栅格图层使用,此时我们不仅仅可以选择加载多波段的数据,同时还可以对栅格数据进行简单的数学计算。

View File

@ -1,5 +1,5 @@
---
title: MVT
title: MVTTile 矢量瓦片
order: 6
---
@ -9,12 +9,34 @@ L7 加载矢量瓦片地图的时候需要在 `source` 中对瓦片服务进行
## parser
- type string 固定值为 `mvt`
- tileSize number 请求瓦片的大小
- zoomOffset number 瓦片请求瓦片层级的偏移
- maxZoom number 瓦片加载最大 `zoom`
- minZoom number 瓦片加载最小 `zoom`
- extent [number, number, number, number] 地图显示范围
### type
<description> _string_ **必选** _default:_ mvt</description>
### tileSize `number`
<description> _number_ **可选** _default:_ 256</description>
请求瓦片的大小
### zoomOffset
<description> number **可选** _default:_ 0</description>
瓦片请求瓦片层级的偏移
### maxZoom
<description> _number_ **可选** _default:_ 0</description>
瓦片最大缩放等级 `20`
### minZoom
<description> _number_ **可选** _default:_ 2-</description>
瓦片最小缩放等
### extent `[number, number, number, number]`
<description> _number[]_ **可选** 不限制:\_ </description>
地图显示范围
```javascript
const tileSource = new Source(

View File

@ -7,20 +7,4 @@ order: 5
Raster 图层主要实现栅格数据的可视化,栅格数据主要来源是卫星遥感数据,如数字高程图,植被分布图,夜光图。
## 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],
},
});
```
<embed src="@/docs/api/source/raster/raster_single.md"></embed>

View File

@ -0,0 +1,266 @@
### data
多波段支持两种数据方式,栅格数据坐标系只支持 3857 投影的栅格
- 单文件多波段
- 多个单波段文件组成多波段
#### 单文件多波段
data 为未解析过 tiff arraybuffer 数据,在 parser 中 通过 format 进行数据标准化
```ts
const url1 = 'https://gw.alipayobjects.com/zos/raptor/1667832825992/LC08_3857_clip_2.tif';
async function getTiffData(url: string) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
return arrayBuffer;
}
}
layer.source(
[
{
data: tiffdata,
bands: [6, 5, 2].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: {
type: 'rgb',
},
extent: [
130.39565357746957, 46.905730725742366, 130.73364094187343,
47.10217234153133,
],
},
},
)
```
### parser
- type: raster
- extent: 栅格的经纬度范围 [minlng, minlat,maxLng, maxLat]
根据栅格数据的经纬度范围,将其添加到地图上。
```javascript
layer.source(rasterData, {
parser: {
type: 'raster',
extent: [121.168, 30.2828, 121.384, 30.4219],
},
});
```
用户可以直接传入栅格文件的二进制数据。
- 支持传入多文件的数据。
- 支持指定某个栅格文件要提取的波段。
```js
interface IBandsData {
data: ArrayBuffer; // 请求加载的栅格文件的二进制数据
bands?: number[]; // 指定加载该栅格文件的波段
}
// 默认加载 0 波段的数据
const source = new Source({ data: tiffData });
// 指定加载 tiffData 0 波段的数据
// 指定加载 tiffData2 0、1 波段的数据
const source2 = new Source([
{ data: tiffData, bands: [0] },
{ data: tiffData2, bands: [0, 1] },
]);
```
#### parser
<description> _IParser_ **必选** </description>
为使用栅格数据的使用提供必要的参数和方法。
```js
interface IParser {
type: string;
format: IRasterFormat;
operation: IOperation;
extent: number[];
}
```
##### type
<description> _string_ **必选** </description>
- 输出结果为单通道数据的时候值为 raster
- 输出结果为多通道彩色的时候值为 rasterRgb
##### format: IRasterFormat
<description> _IFormat_ **必选** </description>
`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<IRasterData | IRasterData[]>;
const source = new Source(data, {
parser: {
format: async (data, bands) => {
...
return {
rasterData: bandData,
width: 256;
height: 256;
}
}
}
})
```
1. `format` 方法的返回值为栅格数据(`rasterData`)以及表示大小的 `width`、`height` 参数。
2. `format` 方法可以返回多份数据,表示从当前栅格文件中提取多份波段的数据。
##### operation: IOperation
<description> _IOperation_ **可选** </description>
在加载多波段数据的时候我们可以通过 `operation` 配置波段数据的运算。
🌟 我们可以不配置 `operation`,此时默认使用第一个栅格文件提取的第一个波段数据
1. `operation` 可以是一个函数,`allbands` 是我们从所有栅格文件中提取的所有波段数据的集合。
```js
const parser = {
operation: (allBands) => {
// operation 可以是一个函数allbands 是我们从所有栅格文件中提取的所有波段数据的集合,
// 在设立 allbands 就是 [band0]
// 函数的返回值是单纯的波段数据,在这里我们直接返回第一个波段的数据
return allBands[0].rasterData;
},
};
```
2. `operation` 可以是以数组形式存在的计算表达式.
```js
// 下面表达式可以转述为 band1 * 0.5表示将波段1 的值都乘上 0.5 并返回
const parser = {
operation: ['*', ['band', 1], 0.5],
};
```
3. `operation` 可以嵌套使用:`['+', ['*', ['band', 0], 0.2], ['band', 1]]]`,返回结果为:`band0 * 0.2 + band1`。
4. `operation` 可以直接指定结果:`['band', 0]`。
5. `operation` 支持以下的数学运算。
```js
/** 数学运算 根据计算表达式进行数学运算
* * * Math operators:
* `['*', value1, value2]` 返回 `value1 * value2`
* `['/', value1, value2]` 返回 `value1 / value2`
* `['+', value1, value2]` 返回 `value1 + value2`
* `['-', value1, value2]` 返回 `value2 - value1`
* `['%', value1, value2]` 返回 `value1 % value2`
* `['^', value1, value2]` 返回 `value1 ^ value2`
* `['abs', value1]` 返回 `Math.abs(value1)`
* `['floor', value1]` 返回 `Math.floor(value1)`
* `['round', value1]` 返回 `Math.round(value1)`
* `['ceil', value1]` 返回 `Math.ceil(value1)`
* `['sin', value1]` 返回 `Math.sin(value1)`
* `['cos', value1]` 返回 `Math.cos(value1)`
* `['atan', value1, value2]` 返回 `n1===-1?Math.atan(n1): Math.atan2(n1, n2)`
*/
```
##### extent
<description> _number[]_ **必选** </description>
`extent` 描述的是栅格数据覆盖的地理区间,数值指定的是区域的经纬度区间(左下角和右上角)。
### 加载多通道(彩色)影像
我们在使用多波段数据的时候支持根据多波段数据绘制彩色遥感影像,如下图的假彩色影像。
<div>
<div style="width:60%;float:left; margin: 10px;">
<img width="80%" alt="案例" src='https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*jO7kTpuDiOQAAAAAAAAAAAAAARQnAQ'>
</div>
</div>
#### data: IBandsData[] | IBandsData
绘制多通道影像的时候,需要加载多波段数据
#### parser
使用栅格数据的使用提供必要的参数和方法, 具体使用和多波段栅格的 `parser` 保持一致。
##### type
<description> _string_ **必选** </description>
- 输出结果为多通道彩色的时候值为 `rasterRgb`
##### format: IRasterFormat
<description> _IFormat_ **必选** </description>
绘制多通道影像的时候,使用通用的 `format`函数。
##### operation: IOperation
<description> _IOperation_ **必选** </description>
为了绘制多通道影像,我们必须要提供 `operation` 配置指定多通道数据。
1. 在渲染彩色多通道栅格的时候需要额外使用 parser同时彩色栅格图层不再支持 domain、rampColor 等参数,渲染的结果直接由波段计算出的 r、g、b 通道的数值结果控制。
2. 彩色栅格不再兼容旧的数据传值方式(直接传入解析完的栅格数据。
```js
const source = new Source(data, { // 彩色栅格和单通道栅格使用相同的规则
parser: {
type: 'rasterRgb', // 使用独立的 type 类型
format: async (data, bands) {...}, // 彩色栅格和单通道栅格 format 使用相同
// operation 为对象,分别为 rgb 三通道指定计算表达式
// operation 必须要配置
operation: {
r: ['*', ['band', 1], 0.5],
g: ['band', 1],
b: undefined // 缺省配置表达式的通道会默认取 0 号波段的值
}
}
```

View File

@ -0,0 +1,124 @@
### data
多波段支持两种数据方式,栅格数据坐标系只支持 3857 投影的栅格,多波段情况 data 为数组类型
- 单文件多波段
- 多个单波段文件组成多波段
```ts
[
{
data: tiffdata, // arraybuffer 类型栅格源数据
bands: [6, 5, 2].map((v) => v - 1),// 单文件多波段可以不传format 函数使用
},
],
```
#### 单文件多波段
data 为未解析过 tiff arraybuffer 数据,在 parser 中 通过 format 进行数据标准化,
```ts
const url1 = 'https://gw.alipayobjects.com/zos/raptor/1667832825992/LC08_3857_clip_2.tif';
async function getTiffData(url: string) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
return arrayBuffer;
}
}
layer.source(
[
{
data: tiffdata,
bands: [6, 5, 2].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: {
type: 'rgb',
},
extent: [
130.39565357746957, 46.905730725742366, 130.73364094187343,
47.10217234153133,
],
},
},
)
```
### parser
- type: `rasterRgb`
多波段数据影像合成
- extent: 栅格的经纬度范围 [minlng, minlat,maxLng, maxLat]
- operation 合成方式
- type `rgb`
- format 数据处理方法,栅格数据解析方式
- 入参数:
- data: source 传入参数
- bands 波段序号
- 返回参数:
返回数据为数组类型
```ts
[{
rasterData: value[band],// 解析后的数据
width: value.width, // 栅格宽度
height: value.height, // 栅格高度
};
]
```
#### 示例
```ts
layer.source(
[
{
data: tiffdata,
bands: [6, 5, 2].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: {
type: 'rgb',
},
extent: [
130.39565357746957, 46.905730725742366, 130.73364094187343,
47.10217234153133,
],
},
},
)
```

View File

@ -0,0 +1,58 @@
## data
data 解析后的数据,为数组
以 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],
},
});
```

View File

@ -1,5 +1,5 @@
---
title: RasterTile
title: RasterTile 栅格瓦片
order: 7
---
@ -9,24 +9,128 @@ L7 加载栅格瓦片地图的时候需要在 `source` 中对瓦片服务进行
## data
瓦片 URL,仅支持 EPSG 3857 的坐标系
瓦片 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 固定值为 `rasterTile`
- tileSize number 请求瓦片的大小
- zoomOffset number 瓦片请求瓦片层级的偏移
- maxZoom number 瓦片加载最大 `zoom`
- minZoom number 瓦片加载最小 `zoom`
- extent [number, number, number, number] 地图显示范围
- dataType string 固定值为 `image`|`arraybuffer`,用于区分普通的栅格瓦片和数据栅格瓦片
- format func 在 `dataType``arraybuffer` 的时候生效,用于将栅格数据格式化为标准数据
### type
<description> _string_ **必选** _default:_ rasterTile</description>
固定值为 `rasterTile`
### tileSize `number`
<description> _number_ **可选** _default:_ 256</description>
请求瓦片的大小 optional
### zoomOffset
<description> number **可选** _default:_ 0</description>
瓦片请求瓦片层级的偏移
### maxZoom
<description> _number_ **可选** _default:_ 0</description>
瓦片最大缩放等级 `20`
### minZoom 瓦片最小缩放等
<description> _number_ **可选** _default:_ 2-</description>
### extent `[number, number, number, number]` 地图显示范围
<description> _number[]_ **可选** 不限制:\_ </description>
### dataType
<description> _string_ **可选** _default:_ image</description>
瓦片数据类型
- image 图像类型
- arraybuffer 数据类型如 geotiff
### format func,
<description> _func_ **可选** \_default:</description>
数据栅格时使用,用于将栅格数据格式化为标准数据,自定义数据处理函数
### wmtsOptions wmsts 配置
<description> _Object_ **可选** _default:_ null</description>
#### layer
<description> _string_ **必选** _default:_ img</description>
图层
#### tileMatrixset
<description> _string_ **必选** _default:_ w</description>
#### format
<description> _string_ **必选** _default:_ tiles</description>
服务类型
```javascript
const rasterSource = new Source(
@ -40,39 +144,4 @@ const rasterSource = new Source(
},
},
);
const rasterDataSource = new Source(
'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
{
parser: {
type: 'rasterTile',
dataType: 'arraybuffer',
tileSize: 256,
zoomOffset: 0,
extent: [-180, -85.051129, 179, 85.051129],
format: async (data: any) => {
const blob: Blob = new Blob([new Uint8Array(data)], {
type: 'image/png',
});
const img = await createImageBitmap(blob);
ctx.clearRect(0, 0, 256, 256);
ctx.drawImage(img, 0, 0, 256, 256);
let imgData = ctx.getImageData(0, 0, 256, 256).data;
let arr = [];
for (let i = 0; i < imgData.length; i += 4) {
const R = imgData[i];
const G = imgData[i + 1];
const B = imgData[i + 2];
const d = -10000 + (R * 256 * 256 + G * 256 + B) * 0.1;
arr.push(d);
}
return {
rasterData: arr,
width: 256,
height: 256,
};
},
},
},
);
```

View File

@ -1,5 +1,5 @@
---
title: RasterTile
title: RasterTile 栅格瓦片
order: 7
---
@ -9,24 +9,128 @@ L7 加载栅格瓦片地图的时候需要在 `source` 中对瓦片服务进行
## data
瓦片 URL,仅支持 EPSG 3857 的坐标系
瓦片 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 固定值为 `rasterTile`
- tileSize number 请求瓦片的大小
- zoomOffset number 瓦片请求瓦片层级的偏移
- maxZoom number 瓦片加载最大 `zoom`
- minZoom number 瓦片加载最小 `zoom`
- extent [number, number, number, number] 地图显示范围
- dataType string 固定值为 `image`|`arraybuffer`,用于区分普通的栅格瓦片和数据栅格瓦片
- format func 在 `dataType``arraybuffer` 的时候生效,用于将栅格数据格式化为标准数据
### type
<description> _string_ **必选** _default:_ rasterTile</description>
固定值为 `rasterTile`
### tileSize `number`
<description> _number_ **可选** _default:_ 256</description>
请求瓦片的大小 optional
### zoomOffset
<description> number **可选** _default:_ 0</description>
瓦片请求瓦片层级的偏移
### maxZoom
<description> _number_ **可选** _default:_ 0</description>
瓦片最大缩放等级 `20`
### minZoom 瓦片最小缩放等
<description> _number_ **可选** _default:_ 2-</description>
### extent `[number, number, number, number]` 地图显示范围
<description> _number[]_ **可选** 不限制:\_ </description>
### dataType
<description> _string_ **可选** _default:_ image</description>
瓦片数据类型
- image 图像类型
- arraybuffer 数据类型如 geotiff
### format func,
<description> _func_ **可选** \_default:</description>
数据栅格时使用,用于将栅格数据格式化为标准数据,自定义数据处理函数
### wmtsOptions wmsts 配置
<description> _Object_ **可选** _default:_ null</description>
#### layer
<description> _string_ **必选** _default:_ img</description>
图层
#### tileMatrixset
<description> _string_ **必选** _default:_ w</description>
#### format
<description> _string_ **必选** _default:_ tiles</description>
服务类型
```javascript
const rasterSource = new Source(
@ -40,39 +144,4 @@ const rasterSource = new Source(
},
},
);
const rasterDataSource = new Source(
'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
{
parser: {
type: 'rasterTile',
dataType: 'arraybuffer',
tileSize: 256,
zoomOffset: 0,
extent: [-180, -85.051129, 179, 85.051129],
format: async (data: any) => {
const blob: Blob = new Blob([new Uint8Array(data)], {
type: 'image/png',
});
const img = await createImageBitmap(blob);
ctx.clearRect(0, 0, 256, 256);
ctx.drawImage(img, 0, 0, 256, 256);
let imgData = ctx.getImageData(0, 0, 256, 256).data;
let arr = [];
for (let i = 0; i < imgData.length; i += 4) {
const R = imgData[i];
const G = imgData[i + 1];
const B = imgData[i + 2];
const d = -10000 + (R * 256 * 256 + G * 256 + B) * 0.1;
arr.push(d);
}
return {
rasterData: arr,
width: 256,
height: 256,
};
},
},
},
);
```

View File

@ -20,6 +20,13 @@ const source = new Source(data, option);
- parser 数据解析配置
- transforms 数据处理配置
## data
不同 parser 类型对应不同 data 类型
- 瓦片图层 data 为 url 模板,支持 TMS、WMS、WMTS 数据服务
- 非瓦片图层 data 为数据对象
## option
`source` 通过 `option` 来描述如果处理数据, 其中主要包括 `parser``transforms`

View File

@ -23,8 +23,6 @@ scene.getLayerByName(name);
L7 采用队列渲染的机制,所有的图层在内部保存在一个数组中,每一帧的渲染会将图层数组按照 zIndex 的值进行排序,然后遍历数组,将符合条件的图层渲染到场景中
<img width="60%" style="display: block;margin: 0 auto;" alt="案例" src='https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*a5xKRZmhoogAAAAAAAAAAAAAARQnAQ'>
### minZoom
<description> _number_ **optional** _default:_ Mapbox 0-24 高德 2-19)</description>

View File

@ -12,6 +12,14 @@
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*cNMlSLwgjboAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "popup2.ts",
"title": {
"zh": "图层点击 气泡",
"en": "Popup"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*cNMlSLwgjboAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "layerpopup.ts",
"title": {

View File

@ -0,0 +1,74 @@
// @ts-ignore
import { PointLayer, Scene, Popup } 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();

View File

@ -1,9 +0,0 @@
---
title: API
---
地图绘制组件,支持点、线、面, 圆、矩形、的绘制编辑。
# 使用
L7Draw 的使用文件可见 [L7Draw 官网](https://l7draw.antv.vision/)

View File

@ -1,9 +0,0 @@
---
title: API
---
地图绘制组件,支持点、线、面, 圆、矩形、的绘制编辑。
# 使用
L7Draw 的使用文件可见 [L7Draw 官网](https://l7draw.antv.vision/)

View File

@ -1,23 +0,0 @@
// https://gw.alipayobjects.com/zos/antvdemo/assets/2019_clip/ndvi_201905.tif
import { Scene } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import { ControlEvent, DrawControl } from '@antv/l7-draw';
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);
});
});

View File

@ -47,7 +47,7 @@
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-transform-import-css-l7": "^0.0.6",
"cross-env": "^7.0.3",
"dumi": "^2.0.0-rc.13",
"dumi": "^2.0.3",
"gcoord": "^0.3.2",
"geotiff": "^2.0.7",
"gh-pages": "^2.1.1",

View File

@ -96,30 +96,6 @@ function processSchemaOperation(operation: SchemaOperationType,bandsData: IRaste
return [r, g, b];
}
/**
*
* @param bandsData
*/
function combineRGBChannels(bandsData: Uint8Array[]) {
const channelR = bandsData[0];
const channelG = bandsData[1];
const channelB = bandsData[2];
const data = [];
let channelRMax = -Infinity;
let channelGMax = -Infinity;
let channelBMax = -Infinity;
for (let i = 0; i < channelR.length; i++) {
data.push(channelR[i]); channelRMax = Math.max(channelRMax, channelR[i]);
data.push((channelG)[i]); channelGMax = Math.max(channelGMax, channelR[i]);
data.push((channelB)[i]); channelBMax = Math.max(channelBMax, channelR[i]);
}
return {
rasterData:data,
channelRMax,
channelGMax,
channelBMax
};
}
/**
*