mirror of https://gitee.com/antv-l7/antv-l7
docs: add source docs, fix mapbox marker
This commit is contained in:
parent
3a02abfc3a
commit
6322779a78
|
@ -25,6 +25,14 @@ shape 支持
|
|||
|
||||
```
|
||||
|
||||
## source
|
||||
|
||||
点数据类型,根据经纬点绘制图形,目前支持三种数据结构
|
||||
|
||||
- [GeoJOSN]('../source/geojson/#point')
|
||||
- [CSV]()
|
||||
- [JSON](../source/json/#点数据)
|
||||
|
||||
**图片标注**
|
||||
|
||||
通过 `Scene.addImage()` 可以添加图片资源,
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
title: CSV
|
||||
order: 3
|
||||
---
|
||||
|
||||
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 示例](../../../examples/point/bubble#scatter)
|
||||
|
||||
### 线段弧线数据通过 CSV 加载
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
data,
|
||||
{
|
||||
parser:{
|
||||
type:'csv',
|
||||
x:'lng1',
|
||||
y:'lat1' ,
|
||||
x1:'lng1',
|
||||
y1:'lat2' ,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
[CSV 线段数据 demo 示例](../../../examples/gallery/basic#arcCircle)
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
title: CSV
|
||||
order: 3
|
||||
---
|
||||
|
||||
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 示例](../../../examples/point/bubble#scatter)
|
||||
|
||||
### 线段弧线数据通过 CSV 加载
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
data,
|
||||
{
|
||||
parser:{
|
||||
type:'csv',
|
||||
x:'lng1',
|
||||
y:'lat1' ,
|
||||
x1:'lng1',
|
||||
y1:'lat2' ,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
[CSV 线段数据 demo 示例](../../../examples/gallery/basic#arcCircle)
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Image
|
||||
order: 4
|
||||
---
|
||||
|
||||
Image 数据主要用于在地图根据经纬度范围添加图图片,不如一幅纸制地图扫描版你要放在地图显示。
|
||||
|
||||
## parser
|
||||
|
||||
- type: image
|
||||
- extent: 图像的经纬度范围 [minlng, minlat,maxLng, maxLat]
|
||||
|
||||
根据图片的经纬度范围,将图片添加到地图上。
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
extent: [121.168, 30.2828, 121.384, 30.4219],
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Image
|
||||
order: 4
|
||||
---
|
||||
|
||||
Image 数据主要用于在地图根据经纬度范围添加图图片,不如一幅纸制地图扫描版你要放在地图显示。
|
||||
|
||||
## parser
|
||||
|
||||
- type: image
|
||||
- extent: 图像的经纬度范围 [minlng, minlat,maxLng, maxLat]
|
||||
|
||||
根据图片的经纬度范围,将图片添加到地图上。
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
extent: [121.168, 30.2828, 121.384, 30.4219],
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: JSON
|
||||
order: 1
|
||||
order: 2
|
||||
---
|
||||
|
||||
GeoJSON 虽然是通用的的地理数据格式,在具体使用场景中,数据服务人员可能并不熟悉 GeoJON,或者没有生成 GeoJON 的工具, 因此 L7 对数据定义了 Parser 的概念,你的数据可以是任何格式,使用指定数据对应的地理信息字段即可。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: JSON
|
||||
order: 1
|
||||
order: 2
|
||||
---
|
||||
|
||||
GeoJSON 虽然是通用的的地理数据格式,在具体使用场景中,数据服务人员可能并不熟悉 GeoJON,或者没有生成 GeoJON 的工具, 因此 L7 对数据定义了 Parser 的概念,你的数据可以是任何格式,使用指定数据对应的地理信息字段即可。
|
||||
|
@ -39,6 +39,8 @@ layer.source(data, {
|
|||
});
|
||||
```
|
||||
|
||||
[JOSN 数据 demo 示例](../../../examples/gallery/basic)
|
||||
|
||||
### 通用解析方式
|
||||
|
||||
可也解析任意复杂的点,线面
|
||||
|
|
|
@ -40,100 +40,25 @@ layer.source(data);
|
|||
|
||||
#### JSON
|
||||
|
||||
[JSON 数据格式解析](../json)
|
||||
[JSON 数据格式解析](./json)
|
||||
|
||||
#### csv
|
||||
|
||||
点,线数据配置项同 json 数据类型
|
||||
[CSV 数据格式解析](./csv)
|
||||
|
||||
```javascript
|
||||
layer.source(data, {
|
||||
parser: {
|
||||
type: 'csv',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng1',
|
||||
y1: 'lat2',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**栅格数据类型 **
|
||||
栅格数据类型
|
||||
|
||||
#### image
|
||||
|
||||
根据图片的经纬度范围,将图片添加到地图上。 配置项
|
||||
|
||||
- type: image
|
||||
- extent: 图像的经纬度范围 []
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
extent: [121.168, 30.2828, 121.384, 30.4219],
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
#### raster
|
||||
|
||||
栅格数据类型,主要表示遥感数据类型 data 栅格数据的二维矩阵数据 parser 配置项
|
||||
|
||||
- type raster
|
||||
- width 数据宽度二维矩阵 columns
|
||||
- height 数据高度
|
||||
- min 数据最大值
|
||||
- max 数据最小值
|
||||
- extent 经纬度范围
|
||||
|
||||
```javascript
|
||||
source(values, {
|
||||
parser: {
|
||||
type: 'raster',
|
||||
width: n,
|
||||
height: m,
|
||||
min: 0,
|
||||
max: 8000,
|
||||
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||
},
|
||||
});
|
||||
```
|
||||
[Image 数据格式解析](./image)
|
||||
|
||||
### transforms
|
||||
|
||||
目前支持三种数据处理方法 map,grid,hexagon transform 配置项
|
||||
目前支持两种热力图使用的数据处理方法 grid,hexagon transform 配置项
|
||||
|
||||
- type 数据处理类型
|
||||
- tansform cfg 数据处理配置项
|
||||
|
||||
#### map
|
||||
|
||||
数据处理,支持自定义 callback 函数
|
||||
|
||||
- callback:function 回调函数
|
||||
|
||||
```javascript
|
||||
layer.source(data, {
|
||||
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;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
#### grid
|
||||
|
||||
生成方格网布局,根据数据字段统计,主要在网格热力图中使用
|
||||
|
@ -163,4 +88,4 @@ layer.source(data, {
|
|||
- type: 'hexagon',
|
||||
- size: 网格半径
|
||||
- field: 数据统计字段
|
||||
- method:聚合方法 count,max,min,sum,mean5 个统计维度
|
||||
- method:聚合方法 count,max,min,sum,mean 5 个统计维度
|
||||
|
|
|
@ -7,6 +7,13 @@ order: 0
|
|||
|
||||
source 地理数据处理模块,主要包含数据解析(parser),和数据处理(transform);
|
||||
|
||||
- data
|
||||
- option
|
||||
- cluster **boolean** 是否聚合
|
||||
- clusterOption 聚合配置项
|
||||
- parser 数据解析配置
|
||||
- transforms 数据处理配置
|
||||
|
||||
### parser
|
||||
|
||||
不同数据类型处理成统一数据格式。矢量数据包括 GeoJON, CSV,Json 等不同数据格式,栅格数据,包括 Raster,Image 数据。将来还会支持瓦片格式数据。
|
||||
|
@ -23,6 +30,14 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据
|
|||
|
||||
## API
|
||||
|
||||
### cluster 可选 可以只设置 cluster
|
||||
|
||||
### clusterOption 可选
|
||||
|
||||
- radius 聚合半径 **number** default 40
|
||||
- minZoom: 最小聚合缩放等级 **number** default 0
|
||||
- maxZoom: 最大聚合缩放等级 **number** default 16
|
||||
|
||||
### parser
|
||||
|
||||
**配置项**
|
||||
|
@ -40,100 +55,25 @@ layer.source(data);
|
|||
|
||||
#### JSON
|
||||
|
||||
[JSON 数据格式解析](../json)
|
||||
[JSON 数据格式解析](./json)
|
||||
|
||||
#### csv
|
||||
|
||||
点,线数据配置项同 json 数据类型
|
||||
[CSV 数据格式解析](./csv)
|
||||
|
||||
```javascript
|
||||
layer.source(data, {
|
||||
parser: {
|
||||
type: 'csv',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng1',
|
||||
y1: 'lat2',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**栅格数据类型 **
|
||||
栅格数据类型
|
||||
|
||||
#### image
|
||||
|
||||
根据图片的经纬度范围,将图片添加到地图上。 配置项
|
||||
|
||||
- type: image
|
||||
- extent: 图像的经纬度范围 []
|
||||
|
||||
```javascript
|
||||
layer.source(
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
extent: [121.168, 30.2828, 121.384, 30.4219],
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
#### raster
|
||||
|
||||
栅格数据类型,主要表示遥感数据类型 data 栅格数据的二维矩阵数据 parser 配置项
|
||||
|
||||
- type raster
|
||||
- width 数据宽度二维矩阵 columns
|
||||
- height 数据高度
|
||||
- min 数据最大值
|
||||
- max 数据最小值
|
||||
- extent 经纬度范围
|
||||
|
||||
```javascript
|
||||
source(values, {
|
||||
parser: {
|
||||
type: 'raster',
|
||||
width: n,
|
||||
height: m,
|
||||
min: 0,
|
||||
max: 8000,
|
||||
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||
},
|
||||
});
|
||||
```
|
||||
[Image 数据格式解析](./image)
|
||||
|
||||
### transforms
|
||||
|
||||
目前支持三种数据处理方法 map,grid,hexagon transform 配置项
|
||||
目前支持两种热力图使用的数据处理方法 grid,hexagon transform 配置项
|
||||
|
||||
- type 数据处理类型
|
||||
- tansform cfg 数据处理配置项
|
||||
|
||||
#### map
|
||||
|
||||
数据处理,支持自定义 callback 函数
|
||||
|
||||
- callback:function 回调函数
|
||||
|
||||
```javascript
|
||||
layer.source(data, {
|
||||
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;
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
#### grid
|
||||
|
||||
生成方格网布局,根据数据字段统计,主要在网格热力图中使用
|
||||
|
|
|
@ -15,8 +15,11 @@ Current version: ![L7 2.0版本号](https://badgen.net/npm/v/@antv/l7/beta)
|
|||
|
||||
Include the L7 JS JavaScript <head> of your HTML file.
|
||||
|
||||
:warning: 如果需要引用第三方地图API,请确保在先引入第三方API,然后引入L7
|
||||
|
||||
```html
|
||||
<head>
|
||||
<! --引入第三方地图JSAPI-->
|
||||
<script src='https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.0-beta.19/dist/l7.js'>
|
||||
</script>
|
||||
</head>
|
||||
|
@ -41,6 +44,7 @@ npm install --save @antv/l7-maps;
|
|||
|
||||
```
|
||||
|
||||
|
||||
### 初始化地图
|
||||
|
||||
#### 使用 高德 底图
|
||||
|
@ -80,3 +84,76 @@ const scene = new Scene({
|
|||
|
||||
```
|
||||
|
||||
### React中使用
|
||||
|
||||
React 组件待开发,期待和大家共建l7-react 目前可以暂时以 Submodule 方式使用
|
||||
|
||||
```
|
||||
import { Scene, PolygonLayer } from '@antv/l7';
|
||||
import { AMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class AMapExample extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new AMap({
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
zoom: 3,
|
||||
token: 'pg.xxx', // 高德或者 Mapbox 的 token
|
||||
}),
|
||||
});
|
||||
const layer = new PolygonLayer({});
|
||||
|
||||
layer
|
||||
.source(await response.json())
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
⚠️组件 Unmount 时需要通过 scene.destroy() 手动销毁场景。
|
||||
|
||||
更多React使用 [示例查看](https://github.com/antvis/L7/tree/master/stories)
|
||||
|
||||
### Vue 欢迎补充
|
|
@ -44,67 +44,71 @@ const scene = new Scene({
|
|||
zoom: 3.802
|
||||
})
|
||||
});
|
||||
Promise.all([
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/5b772136-a1f4-4fc5-9a80-9f9974b4b182.json'
|
||||
).then(d => d.json()),
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/f3c467a4-9ae0-4f08-bb5f-11f9c869b2cb.json'
|
||||
).then(d => d.json())
|
||||
]).then(function onLoad([ center, population ]) {
|
||||
const popobj = {};
|
||||
population.forEach(element => {
|
||||
popobj[element.Code] =
|
||||
element['Population, female (% of total) (% of total)'];
|
||||
});
|
||||
// 数据绑定
|
||||
addChart();
|
||||
scene.render();
|
||||
function addChart() {
|
||||
Promise.all([
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/5b772136-a1f4-4fc5-9a80-9f9974b4b182.json'
|
||||
).then(d => d.json()),
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/f3c467a4-9ae0-4f08-bb5f-11f9c869b2cb.json'
|
||||
).then(d => d.json())
|
||||
]).then(function onLoad([ center, population ]) {
|
||||
const popobj = {};
|
||||
population.forEach(element => {
|
||||
popobj[element.Code] =
|
||||
element['Population, female (% of total) (% of total)'];
|
||||
});
|
||||
// 数据绑定
|
||||
|
||||
center.features = center.features.map(fe => {
|
||||
fe.properties.female = popobj[fe.properties.id] * 1 || 0;
|
||||
return fe;
|
||||
});
|
||||
center.features.forEach(point => {
|
||||
const el = document.createElement('div');
|
||||
const coord = point.geometry.coordinates;
|
||||
const v = point.properties.female * 1;
|
||||
if (v < 1 || (v > 46 && v < 54)) {
|
||||
return;
|
||||
}
|
||||
const size = 60;
|
||||
const data = [
|
||||
{
|
||||
type: '男性',
|
||||
value: 100.0 - v.toFixed(2)
|
||||
},
|
||||
{
|
||||
type: '女性',
|
||||
value: v.toFixed(2) * 1
|
||||
center.features = center.features.map(fe => {
|
||||
fe.properties.female = popobj[fe.properties.id] * 1 || 0;
|
||||
return fe;
|
||||
});
|
||||
center.features.forEach(point => {
|
||||
const el = document.createElement('div');
|
||||
const coord = point.geometry.coordinates;
|
||||
const v = point.properties.female * 1;
|
||||
if (v < 1 || (v > 46 && v < 54)) {
|
||||
return;
|
||||
}
|
||||
];
|
||||
const chart = new G2.Chart({
|
||||
container: el,
|
||||
width: size,
|
||||
height: size,
|
||||
render: 'svg',
|
||||
padding: 0
|
||||
const size = 60;
|
||||
const data = [
|
||||
{
|
||||
type: '男性',
|
||||
value: 100.0 - v.toFixed(2)
|
||||
},
|
||||
{
|
||||
type: '女性',
|
||||
value: v.toFixed(2) * 1
|
||||
}
|
||||
];
|
||||
const chart = new G2.Chart({
|
||||
container: el,
|
||||
width: size,
|
||||
height: size,
|
||||
render: 'svg',
|
||||
padding: 0
|
||||
});
|
||||
chart.source(data);
|
||||
chart.legend(false);
|
||||
chart.tooltip(false);
|
||||
chart.coord('theta', {
|
||||
radius: 0.9,
|
||||
innerRadius: 0.6
|
||||
});
|
||||
chart
|
||||
.intervalStack()
|
||||
.position('value')
|
||||
.color('type', [ '#5CCEA1', '#5B8FF9' ])
|
||||
.opacity(1);
|
||||
chart.render();
|
||||
const marker = new Marker({ element: el }).setLnglat({
|
||||
lng: coord[0],
|
||||
lat: coord[1]
|
||||
});
|
||||
scene.addMarker(marker);
|
||||
});
|
||||
chart.source(data);
|
||||
chart.legend(false);
|
||||
chart.tooltip(false);
|
||||
chart.coord('theta', {
|
||||
radius: 0.9,
|
||||
innerRadius: 0.6
|
||||
});
|
||||
chart
|
||||
.intervalStack()
|
||||
.position('value')
|
||||
.color('type', [ '#5CCEA1', '#5B8FF9' ])
|
||||
.opacity(1);
|
||||
chart.render();
|
||||
const marker = new Marker({ element: el }).setLnglat({
|
||||
lng: coord[0],
|
||||
lat: coord[1]
|
||||
});
|
||||
scene.addMarker(marker);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export default class MarkerService implements IMarkerService {
|
|||
private markers: IMarker[] = [];
|
||||
private unAddMarkers: IMarker[] = [];
|
||||
public addMarker(marker: IMarker): void {
|
||||
if (!this.mapsService.map && this.mapsService.getMarkerContainer()) {
|
||||
if (this.mapsService.map && this.mapsService.getMarkerContainer()) {
|
||||
this.markers.push(marker);
|
||||
marker.addTo(this.scene);
|
||||
} else {
|
||||
|
|
|
@ -106,7 +106,6 @@ export interface ILayer {
|
|||
*/
|
||||
addPlugin(plugin: ILayerPlugin): ILayer;
|
||||
getSource(): ISource;
|
||||
isSourceNeedUpdate(): boolean;
|
||||
setSource(source: ISource): void;
|
||||
setEncodedData(encodedData: IEncodeFeature[]): void;
|
||||
getEncodedData(): IEncodeFeature[];
|
||||
|
|
|
@ -61,6 +61,7 @@ export interface ISource {
|
|||
data: IParserData;
|
||||
cluster: boolean;
|
||||
clusterOptions: Partial<IClusterOptions>;
|
||||
updateClusterData(zoom: number): void;
|
||||
}
|
||||
export interface IRasterCfg {
|
||||
extent: [number, number, number, number];
|
||||
|
|
|
@ -371,30 +371,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
this.buildModels();
|
||||
return this;
|
||||
}
|
||||
|
||||
public isSourceNeedUpdate() {
|
||||
const cluster = this.layerSource.cluster;
|
||||
if (cluster) {
|
||||
const { zoom = 0, bbox = [0, 0, 0, 0] } = this.layerSource.clusterOptions;
|
||||
const newZoom = this.mapService.getZoom();
|
||||
const bounds = this.mapService.getBounds();
|
||||
const newBbox: [number, number, number, number] = [
|
||||
bounds[0][0],
|
||||
bounds[0][1],
|
||||
bounds[1][0],
|
||||
bounds[1][1],
|
||||
];
|
||||
// ||
|
||||
// bbox[0] !== newBbox[0] ||
|
||||
// bbox[2] !== newBbox[2]
|
||||
if (Math.abs(zoom - newZoom) > 1) {
|
||||
this.layerSource.updateClusterData(Math.floor(newZoom), newBbox);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public style(options: object & Partial<ILayerConfig>): ILayer {
|
||||
const { passes, ...rest } = options;
|
||||
|
||||
|
@ -537,12 +513,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
const bounds = this.mapService.getBounds();
|
||||
const zoom = this.mapService.getZoom();
|
||||
if (this.layerSource.cluster) {
|
||||
this.layerSource.updateClusterData(zoom, [
|
||||
bounds[0][0],
|
||||
bounds[0][1],
|
||||
bounds[1][0],
|
||||
bounds[1][1],
|
||||
]);
|
||||
this.layerSource.updateClusterData(zoom);
|
||||
}
|
||||
}
|
||||
public getSource() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import { ILayer, ILayerPlugin } from '@antv/l7-core';
|
||||
import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core';
|
||||
import Source from '@antv/l7-source';
|
||||
import { injectable } from 'inversify';
|
||||
|
||||
@injectable()
|
||||
export default class DataSourcePlugin implements ILayerPlugin {
|
||||
protected mapService: IMapService;
|
||||
public apply(layer: ILayer) {
|
||||
this.mapService = layer.getContainer().get<IMapService>(TYPES.IMapService);
|
||||
layer.hooks.init.tap('DataSourcePlugin', () => {
|
||||
const { data, options } = layer.sourceOption;
|
||||
layer.setSource(new Source(data, options));
|
||||
|
@ -12,7 +14,12 @@ export default class DataSourcePlugin implements ILayerPlugin {
|
|||
|
||||
// 检测数据是不否需要更新
|
||||
layer.hooks.beforeRenderData.tap('DataSourcePlugin', (flag) => {
|
||||
if (layer.isSourceNeedUpdate()) {
|
||||
const source = layer.getSource();
|
||||
const cluster = source.cluster;
|
||||
const { zoom = 0, maxZoom = 16 } = source.clusterOptions;
|
||||
const newZoom = this.mapService.getZoom();
|
||||
if (cluster && Math.abs(zoom - newZoom) > 1 && maxZoom > zoom) {
|
||||
source.updateClusterData(Math.floor(newZoom) + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -20,6 +20,6 @@ describe('source constructor', () => {
|
|||
field: 'mag',
|
||||
},
|
||||
});
|
||||
source.updateClusterData(2, [10, 0, 130, 75]);
|
||||
source.updateClusterData(2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import {
|
||||
IClusterOptions,
|
||||
IMapService,
|
||||
IParserCfg,
|
||||
IParserData,
|
||||
ISourceCFG,
|
||||
ITransform,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import { extent } from '@antv/l7-utils';
|
||||
import {
|
||||
|
@ -14,13 +17,13 @@ import {
|
|||
Properties,
|
||||
} from '@turf/helpers';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { Container } from 'inversify';
|
||||
import { cloneDeep, isFunction, isString } from 'lodash';
|
||||
import Supercluster from 'supercluster';
|
||||
import { SyncHook } from 'tapable';
|
||||
import { getParser, getTransform } from './';
|
||||
import { statMap } from './utils/statistics';
|
||||
import { getColumn } from './utils/util';
|
||||
|
||||
export default class Source extends EventEmitter {
|
||||
public data: IParserData;
|
||||
|
||||
|
@ -82,13 +85,9 @@ export default class Source extends EventEmitter {
|
|||
this.init();
|
||||
}
|
||||
|
||||
public updateClusterData(
|
||||
zoom: number,
|
||||
bbox: [number, number, number, number],
|
||||
): void {
|
||||
public updateClusterData(zoom: number): void {
|
||||
const { method = 'sum', field } = this.clusterOptions;
|
||||
let data = this.clusterIndex.getClusters(bbox, zoom);
|
||||
this.clusterOptions.bbox = bbox;
|
||||
let data = this.clusterIndex.getClusters(this.extent, zoom);
|
||||
this.clusterOptions.zoom = zoom;
|
||||
data.forEach((p) => {
|
||||
if (!p.id) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import Chart from './components/chart';
|
||||
import Marker from './components/Marker';
|
||||
import Popup from './components/Popup';
|
||||
import Scale from './components/Scale';
|
||||
|
@ -9,4 +10,5 @@ storiesOf('UI 组件', module)
|
|||
.add('Zoom', () => <Zoom />)
|
||||
.add('Scale', () => <Scale />)
|
||||
.add('Marker', () => <Marker />)
|
||||
.add('Chart', () => <Chart />)
|
||||
.add('Popup', () => <Popup />);
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
// @ts-ignore
|
||||
import * as G2 from '@antv/g2';
|
||||
import { Marker, Scene } from '@antv/l7';
|
||||
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class ChartComponent extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
center: [52.21496184144132, 24.121126851768906],
|
||||
zoom: 3.802,
|
||||
}),
|
||||
});
|
||||
addChart();
|
||||
scene.render();
|
||||
function addChart() {
|
||||
Promise.all([
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/5b772136-a1f4-4fc5-9a80-9f9974b4b182.json',
|
||||
).then((d) => d.json()),
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/f3c467a4-9ae0-4f08-bb5f-11f9c869b2cb.json',
|
||||
).then((d) => d.json()),
|
||||
]).then(function onLoad([center, population]) {
|
||||
const popobj: { [key: string]: any } = {};
|
||||
population.forEach((element: any) => {
|
||||
popobj[element.Code] =
|
||||
element['Population, female (% of total) (% of total)'];
|
||||
});
|
||||
// 数据绑定
|
||||
|
||||
center.features = center.features.map((fe: any) => {
|
||||
fe.properties.female = popobj[fe.properties.id] * 1 || 0;
|
||||
return fe;
|
||||
});
|
||||
center.features.forEach((point: any) => {
|
||||
const el = document.createElement('div');
|
||||
const coord = point.geometry.coordinates;
|
||||
const v = (point.properties.female * 1) as number;
|
||||
if (v < 1 || (v > 46 && v < 54)) {
|
||||
return;
|
||||
}
|
||||
const size = 60;
|
||||
const data = [
|
||||
{
|
||||
type: '男性',
|
||||
value: 100.0 - Number(v.toFixed(2)),
|
||||
},
|
||||
{
|
||||
type: '女性',
|
||||
value: v.toFixed(2),
|
||||
},
|
||||
];
|
||||
const chart = new G2.Chart({
|
||||
container: el,
|
||||
width: size,
|
||||
height: size,
|
||||
// render: 'svg',
|
||||
padding: 0,
|
||||
});
|
||||
chart.source(data);
|
||||
chart.legend(false);
|
||||
chart.tooltip(false);
|
||||
chart.coord('theta', {
|
||||
radius: 0.9,
|
||||
innerRadius: 0.6,
|
||||
});
|
||||
chart
|
||||
.intervalStack()
|
||||
.position('value')
|
||||
.color('type', ['#5CCEA1', '#5B8FF9'])
|
||||
.opacity(1);
|
||||
chart.render();
|
||||
const marker = new Marker({ element: el }).setLnglat({
|
||||
lng: coord[0],
|
||||
lat: coord[1],
|
||||
});
|
||||
scene.addMarker(marker);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -36,9 +36,6 @@ export default class Point3D extends React.Component {
|
|||
.scale('point_count', {
|
||||
type: 'quantile',
|
||||
})
|
||||
.filter('point_count', (point_count: number) => {
|
||||
return point_count > 1;
|
||||
})
|
||||
.size('point_count', [5, 10, 15, 20, 25])
|
||||
.color('red')
|
||||
.style({
|
||||
|
@ -46,7 +43,6 @@ export default class Point3D extends React.Component {
|
|||
strokeWidth: 1,
|
||||
});
|
||||
scene.addLayer(pointLayer);
|
||||
console.log(pointLayer);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
Loading…
Reference in New Issue