Merge pull request #9 from antvis/master

merge
This commit is contained in:
Parry 2020-02-01 19:25:34 +08:00 committed by GitHub
commit 4125b6226d
114 changed files with 1357 additions and 686 deletions

13
.storybook/main.js Normal file
View File

@ -0,0 +1,13 @@
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = {
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.stories\**.svg$/,
loader: 'svg-inline-loader'
}
);
return config;
},
};

View File

@ -31,6 +31,10 @@ module.exports = ({ config }) => {
test: /\.stories\.css?$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.stories\.svg$/,
loader: 'svg-inline-loader'
}
);
config.resolve.extensions.push('.ts', '.tsx', '.js', '.glsl');

View File

@ -1,96 +1,74 @@
---
title: Control
order: 1
order: 3
---
# control
地图组件 用于控制地图的状态如果平移,缩放,或者展示地图一些的辅助信息如图例,比例尺
## 构造函数
L7 目前支持 Control
```javascript
const baseControl = new L7.Control.Base(option);
```
- Zoom 放大缩小
- Scale 比例尺
- Layers 图层列表
## 构造函数
#### option
position: `string` 控件位置支持是个方位 `bottomright, topright, bottomleft, topleft`
position: `string` 控件位置支持是个方位
#### scene 内置地图组件
- bottomright
- topright
- bottomleft,
- topleft`
zoom 地图放大缩小   默认添加<br />Scale 地图比例尺     默认添加<br />attribution 地图数据属性    默认添加<br />layer 图层列表
### 组件介绍
**scene 配置项设置控件添加状态**
```javascript
scene = new L7.scene({
zoomControl: true,
scaleControl: true,
attributionControl: true,
});
```
import { Scale, Layers, Zoom } from '@antv/l7';
####
```
#### Zoom
放大缩小组件 默认 左上角
放大缩小组件 默认左上角
```javascript
new L7.Control.Zoom({
const zoomControl = new Zoom({
position: 'topleft',
}).addTo(scene);
});
scene.addControl(zoomControl);
```
#### Scale
比例尺组件默认左下角
比例尺组件 默认左下角
```javascript
new L7.Control.Scale({
const scaleControl = new Scale({
position: 'bottomleft',
}).addTo(scene);
});
scene.addControl(scaleControl);
```
#### attribution
#### Layers
默认右下角
图层列表目前支持可视化的图层控制
```javascript
new L7.Control.Attribution({
position: 'bottomleft',
}).addTo(scene);
```
#### layer
图层列表目前只支持可视化 overlayers 图层控制
```javascript
var overlayers = {
围栏填充: layer,
围栏边界: layer2,
const overlayers = {
点图层: layer,
};
new L7.Control.Layers({
overlayers: overlayers,
}).addTo(scene);
const layersControl = new Layers({
overlayers,
});
scene.addControl(layersControl);
```
## 方法
#### onAdd
组件添加到地图 Scene 时调用,自定义组件时需要实现此方法
#### addTo
添加到地图 scene
```javascript
control.addTo(scene);
```
#### setPosition
设置组件位置
@ -106,34 +84,3 @@ control.setPosition('bottomright');
```javascript
control.remove();
```
## 示例代码
#### 自定义图例控件
[源码](https://antv.alipay.com/zh-cn/l7/1.x/demo/component/extendControl.html)
```javascript
var legend = new L7.Control.Base({
position: 'bottomright',
});
legend.onAdd = function() {
var el = document.createElement('div');
el.className = 'infolegend legend';
var grades = [0, 8, 15, 30, 65, 120];
for (var i = 0; i < grades.length; i++) {
el.innerHTML +=
'<i style="background:' +
colors[i] +
'"></i> ' +
grades[i] +
(grades[i + 1] ? '' + grades[i + 1] + '<br>' : '+');
}
return el;
};
legend.addTo(scene);
```
##
## FAQ

View File

@ -3,7 +3,7 @@ title: Control
order: 3
---
地图组件 用于控制地图的状态如果平移,缩放,或者展示地图一些的辅助信息如图例比例尺
地图组件用于控制地图的状态如果平移,缩放,或者展示地图一些的辅助信息如图例比例尺
L7 目前支持 Control
@ -57,6 +57,22 @@ scene.addControl(scaleControl);
图层列表目前支持可视化的图层控制
配置项
option 控件配置项
overlayers 将一组图层添加到图层列表,
overlayers Object
key: 列表显示的图层名字可以自定义
layer: 图层对象
overlayers 示例
```javascript
{
"图层一"layer1,
"图层二"layer2,
}
```
```javascript
const overlayers = {
点图层: layer,

View File

@ -62,7 +62,7 @@ scene.addMarker(marker);
#### 默认 Marker
\*\*<br />`const marker = new L7.Marker({color:'blue'})`
`const marker = new L7.Marker({color:'blue'})`
#### 自定义 Marker

View File

@ -3,7 +3,7 @@ title: Marker
order: 3
---
Marker 地图标注 目前只支持 2D dom 标注
Marker 地图标注 目前只支持 2D Dom 标注
## 构造函数
@ -13,9 +13,10 @@ Marker
#### option
- color        `string`   ![map-marker.png](https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*BJ6cTpDcuLcAAAAAAAAAAABkARQnAQ)  设置默认 marker 的颜色
- color        `string` 
![map-marker.png](https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*BJ6cTpDcuLcAAAAAAAAAAABkARQnAQ)  设置默认 marker 的颜色
- element    `Dom|string`    自定义 marker Dom 节点,可以是 dom 实例,也可以是 dom id
- anchor     `string`  锚点位置   支持 center, top, top-left, top-right, bottom, bottom-left,bottom-                        right,left, right
- anchor     `string`  锚点位置   支持 center, top, top-left, top-right, bottom, bottom-left,bottom-right,left, right
- offset    `Array`  偏移量  [ 0, 0 ] 分别表示 X, Y 的偏移量
- extData 用户自定义属性,支持任意数据类型,存储 marker 属性信息
@ -37,6 +38,12 @@ Marker
获取 marker dom Element
### setElement
- element `dom`
设置 element 通过此方法更新 Marker 样式
#### getLngLat
获取 marker 经纬度坐标
@ -45,6 +52,14 @@ Marker
开启或者关闭 marker 弹出框
#### openPopup
打开 Popup
### closePopup
关闭 popup
#### setPopup
为 marker 设置 popup

View File

@ -1,5 +1,5 @@
---
title: Marker Layer
title: Marker 图层
order: 3
---
@ -33,11 +33,20 @@ scene.addMarkerLayer(markerLayer);
#### option
- cluster 是部分聚合 `boolean` 默认 `false`
- cluster 聚合 `boolean` 默认 `false`
- clusterOption 聚合配置
- cluster 是部分聚合
- element `function`
- field `string` 聚合统计字段
- method `sum| max| min| mean`
- element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素
参数feature
point_count 默认 聚合元素个数
clusterData `Array` 聚合节点的原始数据
point_sum 聚合求和 根据 field 和 method 计算
point_max 聚合最大值 根据 field 和 method 计算
point_min 聚合最小值 根据 field 和 method 计算
point_mean 聚合平均值 根据 field 和 method 计算
后续会增加更多配置项目
@ -47,7 +56,7 @@ scene.addMarkerLayer(markerLayer);
参数
- marker `Marker` 需要添加的 Marker
- marker `IMarker` 需要添加的 Marker
添加 Marker
@ -58,6 +67,21 @@ const marker = new Marker().setLnglat(); // 添加进Marker必须设置经纬度
markerLayer.addMarker(marker);
```
为 Marker 添加属性信息,
如果聚合参数设置统计配置项 `field| method`需要为 Marker 添加属性信息
通过 Marker 的 extData[配置项](./marker#option)设置 Marker 属性信息
```javascript
const marker = new Marker({
extData: nodes.features[i].properties,
}).setLnglat({
lng: coordinates[0],
lat: coordinates[1],
});
```
#### removeMarker
从 MarkerLayer 移除 Marker

View File

@ -3,17 +3,18 @@ title: Marker 图层
order: 3
---
MarkerLayer 不同于 PointLayer 图层
MarkerLayer 是 Marker 的升级版Marker 是独立的地图标注MarkerLayer 则是统一管理大量的 Marker 数据。
**技术差异**
- MarkerLayer 地图元素采用 Dom 元素绘制
- Marker Dom 绘制一个地图元素
- MarkerLayer 统一管理多个 DomMarker
- PointLayer 通过 WebGL 绘制元素。
**功能差异**
- MarkerLayer 元素的自定义性比较强,任何 HTML+ CSS 的组合都可以绘制在地图上。
- PointLayer 自定义性比较弱,实现成本比较高,优势可以绘制大量的数据,性能比交互
- MarkerLayer 元素的自定义性比较强,任何 HTML+ CSS 的组合都可以绘制在地图上。
- PointLayer 自定义性比较弱,实现成本比较高,优势可以绘制大量的数据,性能比较好
## 使用
@ -33,13 +34,22 @@ scene.addMarkerLayer(markerLayer);
#### option
- cluster 是部分聚合 `boolean` 默认 `false`
- cluster 聚合 `boolean` 默认 `false`
- clusterOption 聚合配置
- cluster 是部分聚合
- element `function`
后续会增加更多配置项目
- field `string` 聚合统计字段
- method `sum| max| min| mean`
- element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素
参数feature
- point_count 默认 聚合元素个数
- clusterData `Array` 聚合节点的原始数据
- point_sum 聚合求和 根据 field 和 method 计算
- point_max 聚合最大值 根据 field 和 method 计算
- point_min 聚合最小值 根据 field 和 method 计算
- point_mean 聚合平均值 根据 field 和 method 计算
### 方法
@ -47,7 +57,7 @@ scene.addMarkerLayer(markerLayer);
参数
- marker `Marker` 需要添加的 Marker
- marker `IMarker` 需要添加的 Marker
添加 Marker
@ -58,6 +68,21 @@ const marker = new Marker().setLnglat(); // 添加进Marker必须设置经纬度
markerLayer.addMarker(marker);
```
为 Marker 添加属性信息,
如果聚合参数设置统计配置项 `field| method`需要为 Marker 添加属性信息
通过 Marker 的 extData[配置项](./marker#option)设置 Marker 属性信息
```javascript
const marker = new Marker({
extData: nodes.features[i].properties,
}).setLnglat({
lng: coordinates[0],
lat: coordinates[1],
});
```
#### removeMarker
从 MarkerLayer 移除 Marker

View File

@ -1,6 +1,6 @@
---
title: Popup
order: 4
title: popup
order: 0
---
# popup
@ -26,7 +26,24 @@ const popup = new L7.Popup(option);
#### setLnglat
设置 popup 的经纬度位置<br />**参数**lnglat 经纬度数组 [112,32]
设置 popup 的经纬度位置
**参数**lnglat
支持数组
```javascript
[112, 32];
```
经纬度对象
```javascript
{
lng: 112,
lat: 30
}
```
```javascript
popup.setLnglat([112, 32]);
@ -49,17 +66,22 @@ popup.addTo(scene);
设置 popup html 内容
```javascript
var html =
'<p>\u7701\u4EFD\uFF1A' +
feature.s +
'</p>\n <p>\u5730\u533A\uFF1A' +
feature.m +
'</p>\n <p>\u6E29\u5EA6\uFF1A' +
feature.t +
'</p>\n ';
var html = `<p>省份
${feature.s} </p><p>地区
${feature.m}</p><p>数值
${feature.t}</p>`;
popup.setHtml(html);
```
#### setDOMContent
- 参数 htmlNode dom 对象
区别于 setHtml 对象只能传字符串
**tips**
如果需要将 react 组件渲染到 popup 可以用此方法。
#### setText
设置 popup 显示文本内容
@ -68,6 +90,38 @@ popup.setHtml(html);
popup.setText('hello world');
```
#### open
显示 popup
```javascript
popup.open();
```
#### close
显示 popup
```javascript
popup.close();
```
#### open
显示 popup
```javascript
popup.open();
```
#### close
显示 popup
```javascript
popup.close();
```
#### remove
移除 popup
@ -78,6 +132,12 @@ popup.remove();
## 事件
### open
```javascript
popup.on('open', () => {});
```
#### close
```javascript

View File

@ -26,7 +26,24 @@ const popup = new L7.Popup(option);
#### setLnglat
设置 popup 的经纬度位置<br />**参数**lnglat 经纬度数组 [112,32]
设置 popup 的经纬度位置
**参数**lnglat
支持数组
```javascript
[112, 32];
```
经纬度对象
```javascript
{
lng: 112,
lat: 30
}
```
```javascript
popup.setLnglat([112, 32]);
@ -49,17 +66,22 @@ popup.addTo(scene);
设置 popup html 内容
```javascript
var html =
'<p>\u7701\u4EFD\uFF1A' +
feature.s +
'</p>\n <p>\u5730\u533A\uFF1A' +
feature.m +
'</p>\n <p>\u6E29\u5EA6\uFF1A' +
feature.t +
'</p>\n ';
var html = `<p>省份
${feature.s} </p><p>地区
${feature.m}</p><p>数值
${feature.t}</p>`;
popup.setHtml(html);
```
#### setDOMContent
- 参数 htmlNode dom 对象
区别于 setHtml 对象只能传字符串
**tips**
如果需要将 react 组件渲染到 popup 可以用此方法。
#### setText
设置 popup 显示文本内容
@ -68,6 +90,38 @@ popup.setHtml(html);
popup.setText('hello world');
```
#### open
显示 popup
```javascript
popup.open();
```
#### close
显示 popup
```javascript
popup.close();
```
#### open
显示 popup
```javascript
popup.open();
```
#### close
显示 popup
```javascript
popup.close();
```
#### remove
移除 popup
@ -78,6 +132,12 @@ popup.remove();
## 事件
### open
```javascript
popup.on('open', () => {});
```
#### close
```javascript

View File

@ -23,7 +23,7 @@ import { HeatMapLayer } from '@antv/l7';
- type  数据聚合类型 grid
- size  网格半径 单位 米
- field  聚合字段
- method 聚合方法  count,max,min,sum,mean5 个统计维度
- method 聚合方法  count,max,min,sum,mean 5个统计维度
```javascript
@ -57,7 +57,7 @@ layer.source(data, {
```javascript
layer.shape(circle);
layer.shape('circle');
```
@ -69,7 +69,7 @@ layer.shape(circle);
- squareColumn,
```javascript
layer.shape(cylinder);
layer.shape('cylinder');
```
@ -150,7 +150,7 @@ const layer = new HeatmapLayer({})
'#6BD5A0',
'#A7ECB2',
'#D0F4CA'
].reverse()
]
);
scene.addLayer(layer);

View File

@ -21,7 +21,7 @@ import { HeatMapLayer } from '@antv/l7';
- type  数据聚合类型 grid
- size  网格半径 单位 米
- field  聚合字段
- method 聚合方法  count,max,min,sum,mean5 个统计维度
- method 聚合方法  count,max,min,sum,mean 5个统计维度
```javascript
@ -54,7 +54,7 @@ layer.source(data, {
- heaxgon
```javascript
layer.shape(circle);
layer.shape('circle');
```
@ -66,7 +66,7 @@ layer.shape(circle);
- squareColumn,
```javascript
layer.shape(cylinder);
layer.shape('cylinder');
```
@ -146,7 +146,7 @@ const layer = new HeatmapLayer({})
'#6BD5A0',
'#A7ECB2',
'#D0F4CA'
].reverse()
]
);
scene.addLayer(layer);

View File

@ -18,7 +18,7 @@ import { HeatMapLayer } from '@antv/l7';
- type  数据聚合类型 hexagon
- size  网格半径 单位 米
- field  聚合字段
- method 聚合方法  count,max,min,sum,mean5 个统计维度
- method 聚合方法  count,max,min,sum,mean 5个统计维度
```javascript
@ -51,7 +51,7 @@ layer.source(data, {
- heaxgon
```javascript
layer.shape(circle);
layer.shape('circle');
```
@ -63,7 +63,7 @@ layer.shape(circle);
- squareColumn,
```javascript
layer.shape(cylinder);
layer.shape('cylinder');
```

View File

@ -23,7 +23,7 @@ import { HeatMapLayer } from '@antv/l7';
- type  数据聚合类型 hexagon
- size  网格半径 单位 米
- field  聚合字段
- method 聚合方法  count,max,min,sum,mean5 个统计维度
- method 聚合方法 count,max,min,sum,mean 5个统计维度
```javascript
@ -56,7 +56,7 @@ layer.source(data, {
- heaxgon
```javascript
layer.shape(circle);
layer.shape('circle');
```
@ -68,7 +68,7 @@ layer.shape(circle);
- squareColumn,
```javascript
layer.shape(cylinder);
layer.shape('cylinder');
```

View File

@ -39,7 +39,7 @@ layer.size('weight', [0,1])
- colors  颜色数组
- positions 数据区间
:warning: color, position 的长度要相同
⚠️ color, position 的长度要相同
## 完整代码

View File

@ -39,15 +39,13 @@ layer.size('weight', [0,1])
- colors  颜色数组
- positions 数据区间
:warning: color, position 的长度要相同
⚠️ color, position 的长度要相同
## 完整代码
```javascript
heatmapLayer({
zIndex: 2,
})
heatmapLayer()
.source(data)
.size('mag', [0, 1]) // weight映射通道
.style({

View File

@ -120,7 +120,7 @@ cscle('field', scaleConfig)
## 视觉编码方法
可视化编码是将数据转换为可视形式的过程L7 目前支持形状,大小,颜色 3 种视觉通,你可以指定数据字段,为不同要素设置不同的图形属性。
可视化编码是将数据转换为可视形式的过程L7 目前支持形状,大小,颜色 3 种视觉通,你可以指定数据字段,为不同要素设置不同的图形属性。
### size
@ -324,7 +324,7 @@ layer.show();
layer.hide();
```
### isVisable
### isVisible
图层是否可见
@ -420,7 +420,7 @@ layer.setSelect(id);
- x: number 鼠标  在地图位置 x 坐标
- y: number 鼠标  在地图位置 y 坐标
- type: string 鼠标事件类型
- lngLat: ILngLat {lng:number, lat: number }; 鼠标所在位置经纬度
- lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度
- feature: any; 数据选中的地理要素信息
- featureId: number | null; 数据选中的地理要素的 ID
@ -495,27 +495,31 @@ layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件
### inited
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型
图层初始化完成后触发
```javascript
layer.on('inited', (option) => {});
```
### add
图层添加到 scene
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型
### remove
图层移除时触发
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型

View File

@ -120,7 +120,7 @@ cscle('field', scaleConfig)
## 视觉编码方法
可视化编码是将数据转换为可视形式的过程L7 目前支持形状,大小,颜色 3 种视觉通,你可以指定数据字段,为不同要素设置不同的图形属性。
可视化编码是将数据转换为可视形式的过程L7 目前支持形状,大小,颜色 3 种视觉通,你可以指定数据字段,为不同要素设置不同的图形属性。
### size
@ -324,7 +324,7 @@ layer.show();
layer.hide();
```
### isVisable
### isVisible
图层是否可见
@ -420,7 +420,7 @@ layer.setSelect(id);
- x: number 鼠标  在地图位置 x 坐标
- y: number 鼠标  在地图位置 y 坐标
- type: string 鼠标事件类型
- lngLat: ILngLat {lng:number, lat: number }; 鼠标所在位置经纬度
- lngLat: 经度度对象 {lng:number, lat: number }; 鼠标所在位置经纬度
- feature: any; 数据选中的地理要素信息
- featureId: number | null; 数据选中的地理要素的 ID
@ -495,27 +495,31 @@ layer.on('unpick', (ev) => {}); // 图层外的操作的所有事件
### inited
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型
图层初始化完成后触发
```javascript
layer.on('inited', (option) => {});
```
### add
图层添加到 scene
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型
### remove
图层移除时触发
option
参数 option
- target ILayer 当前 layer
- target 当前 layer
- type 事件类型

View File

@ -7,7 +7,7 @@ order: 1
## 使用
### 数据
绘制弧线只需提供起点坐标即可
绘制弧线只需提供起点坐标即可
```javascript
source(data, {
@ -23,7 +23,7 @@ order: 1
### shape
弧线支持种弧线算法
弧线支持种弧线算法
- arc 绘制弧线 通过贝塞尔曲线算法技术弧线
- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线

View File

@ -7,7 +7,7 @@ order: 1
## 使用
### 数据
绘制弧线只需提供起点坐标即可
绘制弧线只需提供起点坐标即可
```javascript
source(data, {
@ -23,7 +23,7 @@ order: 1
### shape
弧线支持种弧线算法
弧线支持种弧线算法
- arc 绘制弧线 通过贝塞尔曲线算法技术弧线
- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线

View File

@ -14,7 +14,7 @@ order: 2
- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线
- arc3d 3d 弧线地图 3D 视角
⚠️ 弧线只需要设置起点坐标即可
⚠️ 弧线只需要设置起点坐标即可
```
new LineLayer()

View File

@ -14,7 +14,7 @@ order: 0
- greatcircle 大圆航线,地图两个点的最近距离不是两个点连线,而是大圆航线
- arc3d 3d 弧线地图 3D 视角
⚠️ 弧线只需要设置起点坐标即可
⚠️ 弧线只需要设置起点坐标即可
```
new LineLayer()

View File

@ -31,11 +31,10 @@ order: 5
**getClustersLeaves(id: string)**
根据id获取聚合节点的数据
根据id获取聚合节点的数据每个聚合节点会有一个唯一ID
- id 聚合数据id
```javascript
@ -73,6 +72,13 @@ const pointLayer = new PointLayer({})
strokeWidth: 1,
});
```
[聚合图使用案例](../../../examples/point/cluster)
### FAQ
PointLayer的聚合图采用WebGL绘制不支持自定义具体聚合样式如果有自定义的需求可以使用MarkerLayer的聚合功能你可以通过Dom完全自定义样式。
[MarkerLayer聚合](../../component/markerLayer)

View File

@ -7,15 +7,14 @@ order: 3
## 使用
### shape
- dot 如果需要使用亮度图可以将shape设置为dot,或者不设置shape
### color
- 无权重
如果数据没有权重可以将颜色设置为常量,渲染时会自动进行颜色叠加,点越多颜色
如果数据没有权重可以将颜色设置为常量,渲染时会自动进行颜色叠加,点越多颜色
- 有权重
为数据有权重可以设置一组同一色相不同亮度的色带
如果数据有权重可以设置一组同一色相,不同亮度的色带,值越大亮度会越亮
```javascript

View File

@ -12,9 +12,9 @@ order: 3
### color
- 无权重
如果数据没有权重可以将颜色设置为常量,渲染时会自动进行颜色叠加,点越多颜色
如果数据没有权重可以将颜色设置为常量,渲染时会自动进行颜色叠加,点越多颜色
- 有权重
为数据有权重可以设置一组同一色相不同亮度的色带
如果数据有权重可以设置一组同一色相,不同亮度的色带,值越大亮度会越亮
```javascript

View File

@ -22,7 +22,7 @@ import { PolygonLayer } from '@antv/l7';
PolyonLayer.shape('fill');
PolyonLayer.shape('line').size(1); // size 表示线宽度
PolyonLayer.shape('extrude'); // size 表示高度
PolyonLayer.shape('extrude').size(10); // size 表示高度
```

View File

@ -37,8 +37,8 @@ import { RasterLayer } from '@antv/l7';
- domain: [ 0, 8000 ] 数据映射区间
- noDataValue Number noDataValue 不会显示
- rampColors: {
colors: [ '#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C' ].reverse(),
colors: [ '#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C' ],
positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
} // 色带
:warning: color, position 的长度要相同
⚠️ color, position 的长度要相同

View File

@ -37,8 +37,8 @@ import { RasterLayer } from '@antv/l7';
- domain: [ 0, 8000 ] 数据映射区间
- noDataValue Number noDataValue 不会显示
- rampColors: {
colors: [ '#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C' ].reverse(),
colors: [ '#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C' ],
positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
} // 色带
:warning: color, position 的长度要相同
⚠️ color, position 的长度要相同

View File

@ -5,8 +5,8 @@ order: 2
# 简介
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持 高德地图和 MapBox 两种。=
L7 在内部解决了不同底图地图直接的差异,同时 L7 层面统一管理地图的操作方法。
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持高德地图和 MapBox 两种。
L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。
## Map

View File

@ -5,8 +5,8 @@ order: 2
# 简介
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持 高德地图和 MapBox 两种。=
L7 在内部解决了不同底图地图直接的差异,同时 L7 层面统一管理地图的操作方法。
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持高德地图和 MapBox 两种。
L7 在内部解决了不同地图底图之间差异,同时 L7 层面统一管理地图的操作方法。
## Map

View File

@ -214,7 +214,10 @@ scene.setCenter([lng, lat]);
scene.setZoomAndCenter(zoom, center);
```
参数zoom {number}<br />center {LngLat}
参数:
- zoom {number}
- center {LngLat}
### setRotation
@ -260,7 +263,10 @@ scene.panTo(LngLat);
scene.panBy(x, y);
```
参数:<br />`x` {number} 水平方向移动像素 向右为正方向<br />      `y` {number} 垂直方向移动像素 向下为正方向
参数:
- `x` {number} 水平方向移动像素 向右为正方向
- `y` {number} 垂直方向移动像素 向下为正方向
### setPitch
@ -270,11 +276,16 @@ scene.panBy(x, y);
scene.setPitch(pitch);
```
参数 :<br />   `pitch` {number}
参数 :
`pitch` {number}
### fitBounds
地图缩放到某个范围内<br />参数 :<br />  `extent` { array} 经纬度范围 [minlng,minlat,maxlng,maxlat]
地图缩放到某个范围内
参数 :
- `extent` { array} 经纬度范围 [minlng,minlat,maxlng,maxlat]
```javascript
scene.fitBounds([112, 32, 114, 35]);
@ -298,11 +309,15 @@ scene.removeLayer(layer);
#### 参数
`eventName` {string} 事件名<br />`hander` {function } 事件回调函数
- `eventName` {string} 事件名
- `handler` {function } 事件回调函数
### off
移除事件监听<br />`eventName` {string} 事件名<br />`hander` {function } 事件回调函数
移除事件监听
- `eventName` {string} 事件名
- `handler` {function } 事件回调函数
### 地图事件

View File

@ -316,11 +316,14 @@ scene.removeLayer(layer);
#### 参数
`eventName` {string} 事件名<br />`hander` {function } 事件回调函数
`eventName` {string} 事件名
`handler` {function } 事件回调函数
### off
移除事件监听<br />`eventName` {string} 事件名<br />`hander` {function } 事件回调函数
移除事件监听
`eventName` {string} 事件名
`handler` {function } 事件回调函数
### 场景事件
@ -363,7 +366,7 @@ scene.on('mouseover', (ev) => {}); // 鼠标移入地图容器内时触发
scene.on('mouseout', (ev) => {}); // 鼠标移出地图容器时触发
scene.on('mouseup', (ev) => {}); // 鼠标在地图上单击抬起时触发
scene.on('mousedown', (ev) => {}); // 鼠标在地图上单击按下时触发
scene.on('rightclick', (ev) => {}); // 鼠标右键单击事件
scene.on('contextmenu', (ev) => {}); // 鼠标右键单击事件
scene.on('dragstart', (ev) => {}); //开始拖拽地图时触发
scene.on('dragging', (ev) => {}); // 拖拽地图过程中触发
scene.on('dragend', (ev) => {}); //停止拖拽地图时触发。如地图有拖拽缓动效果,则在拽停止,缓动开始前触发

View File

@ -8,7 +8,7 @@ L7 支持 CSV 以逗号分隔的 CSV 数据加载。
CSV 是文本数据结构,很难表达复杂的地理数据结构,因此 CSV 仅支持两种数据结构
- 点数据 需要指定经度,纬度坐标
- 线段,弧线数据 需要指定 起点的 经度,纬度坐标
- 线段,弧线数据 需要指定 起点的 经度,纬度坐标
## parser

View File

@ -8,7 +8,7 @@ L7 支持 CSV 以逗号分隔的 CSV 数据加载。
CSV 是文本数据结构,很难表达复杂的地理数据结构,因此 CSV 仅支持两种数据结构
- 点数据 需要指定经度,纬度坐标
- 线段,弧线数据 需要指定 起点的 经度,纬度坐标
- 线段,弧线数据 需要指定 起点的 经度,纬度坐标
## parser

View File

@ -27,7 +27,7 @@ json 数据解析使用对应 JSON parser
如果数据是点数据,只需要设置 x,y 字段即可
如果是线段,弧线数据,需要知道起点坐标既x,y,x1,y1
如果是线段,弧线数据,需要知道起点坐标既x,y,x1,y1
```javascript
layer.source(data, {
@ -122,7 +122,7 @@ layer.source(data, {
- x1 `string` 经度
- x2 `string` 纬度
简易解析只支持两个点组成的线段,主要再绘制弧线的时候比较常用,只需指定线段的起点坐标
简易解析只支持两个点组成的线段,主要再绘制弧线的时候比较常用,只需指定线段的起点坐标
```javascript
const data = [

View File

@ -27,7 +27,7 @@ json 数据解析使用对应 JSON parser
如果数据是点数据,只需要设置 x,y 字段即可
如果是线段,弧线数据,需要知道起点坐标既x,y,x1,y1
如果是线段,弧线数据,需要知道起点坐标既x,y,x1,y1
```javascript
layer.source(data, {
@ -124,7 +124,7 @@ layer.source(data, {
- x1 `string` 经度
- x2 `string` 纬度
简易解析只支持两个点组成的线段,主要再绘制弧线的时候比较常用,只需指定线段的起点坐标
简易解析只支持两个点组成的线段,主要再绘制弧线的时候比较常用,只需指定线段的起点坐标
```javascript
const data = [

View File

@ -7,6 +7,13 @@ order: 0
source 地理数据处理模块主要包含数据解析parser),和数据处理(transform);
- data
- option
- cluster **boolean** 是否聚合
- clusterOption 聚合配置项
- parser 数据解析配置
- transforms 数据处理配置
### parser
不同数据类型处理成统一数据格式。矢量数据包括 GeoJON, CSVJson 等不同数据格式,栅格数据,包括 RasterImage 数据。将来还会支持瓦片格式数据。
@ -23,6 +30,14 @@ source 地理数据处理模块主要包含数据解析parser),和数据
## API
### cluster `boolean` 可选 可以只设置
### clusterOption 可选
- radius 聚合半径 **number** default 40
- minZoom: 最小聚合缩放等级 **number** default 0
- maxZoom: 最大聚合缩放等级 **number** default 16
### parser
**配置项**
@ -38,6 +53,17 @@ source 地理数据处理模块主要包含数据解析parser),和数据
layer.source(data);
```
### Source 更新
如果数据发生改变,可以需要更新数据
可以通过调用 layer 的 setData 方法实现数据的更新
具体见 [Layer](../layer/layer/#setdata)
```javascript
layer.setData(data);
```
#### JSON
[JSON 数据格式解析](./json)
@ -54,6 +80,23 @@ layer.source(data);
### transforms
tranforms 处理的是的标准化之后的数据
标准化之后的数据结构包括 coordinates 地理坐标字段,以及其他属性字段。
处理完之后返回的也是标准数据
```json
[
{
"coordinates": [[]], // 地理坐标字段
"_id": "122", // 标准化之后新增字段
"name": "test",
"value": 1
// ....
}
]
```
目前支持两种热力图使用的数据处理方法 gridhexagon transform 配置项
- type 数据处理类型
@ -88,4 +131,4 @@ layer.source(data, {
- type: 'hexagon',
- size: 网格半径
- field: 数据统计字段
- method:聚合方法   count,max,min,sum,mean 5 个统计维度
- method: 聚合方法   count,max,min,sum,mean 5 个统计维度

View File

@ -30,7 +30,7 @@ source 地理数据处理模块主要包含数据解析parser),和数据
## API
### cluster ``boolean` 可选 可以只设置
### cluster `boolean` 可选 可以只设置
### clusterOption 可选
@ -38,6 +38,8 @@ source 地理数据处理模块主要包含数据解析parser),和数据
- minZoom: 最小聚合缩放等级 **number** default 0
- maxZoom: 最大聚合缩放等级 **number** default 16
[聚合图使用案例](../../../examples/point/cluster)
### parser
**配置项**
@ -109,7 +111,7 @@ tranforms 处理的是的标准化之后的数据
- type: 'grid',
- size: 网格半径
- field: 数据统计字段
- method:聚合方法   count,max,min,sum,mean5 个统计维度
- method: 聚合方法  count,max,min,sum,mean 5 个统计维度
```javascript
layer.source(data, {

View File

@ -1,5 +1,5 @@
---
title: Data
title: 数据
order: 2
---
@ -7,7 +7,9 @@ order: 2
目前L7支持的数据格式有GeoJson,CSV,JSon Image
GeoJSON 支持点、线、面,等所有的空间数据格式。<br />CSV 支持,点,线段,弧线的支持。<br />JSON 支持简单的点、线,面,不支持多点,多线的,多面数据格式。
- GeoJSON 支持点、线、面等所有的标准空间数据格式。
- CSV 支持点、线段、弧线等数据类型。
- JSON 支持简单的点、线,面数据类型,不支持多点,多线的,多面数据格式。
## GeoJSON
@ -55,7 +57,7 @@ GeoJSON 支持点、线、面,等所有的空间数据格式。<br />CSV 支
}
```
#### 全国行政区划GeoJON 支持省市县维度 
## 地理统计分析工具
[turfjs](http://turfjs.org/):  地理数据计算处理统计分析的Javascript 库
## 在线工具
@ -63,3 +65,12 @@ GeoJSON 支持点、线、面,等所有的空间数据格式。<br />CSV 支
[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/)

View File

@ -7,7 +7,9 @@ order: 2
目前L7支持的数据格式有GeoJson,CSV,JSon Image
GeoJSON 支持点、线、面,等所有的空间数据格式。<br />CSV 支持,点,线段,弧线的支持。<br />JSON 支持简单的点、线,面,不支持多点,多线的,多面数据格式。
- GeoJSON 支持点、线、面等所有的标准空间数据格式。
- CSV 支持点、线段、弧线等数据类型。
- JSON 支持简单的点、线,面数据类型,不支持多点,多线的,多面数据格式。
## GeoJSON

View File

@ -1,8 +1,9 @@
---
title: How to start the demo locally
title: 本地运行demo
order: 1
---
### 一、打开L7demo页面
@ -11,7 +12,7 @@ order: 1
<img src="https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*bKT5TrlYlGEAAAAAAAAAAABkARQnAQ" alt="L7 地理可视化" width = "50%" height = "100%">
你可能没有注意,代码区的上方有一排工具按钮,注意了你可能不知道干什么用的
你可能没有注意,代码区的上方有一排工具按钮,。
### 二、打开 codesandbox。
@ -22,7 +23,7 @@ order: 1
<img src="https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*coZsTLbX2FQAAAAAAAAAAABkARQnAQ" alt="L7 地理可视化" width = "50%" height = "100%">
你发现你进入了一个线代码编辑器比较流行,这里面你可以修改代码,并且能够随时看到效果
你发现你进入了一个线代码编辑器,这里面你可以修改代码,并且能够随时看到效果
你可能想说我就想本地跑起来,不想在线修改。
@ -57,6 +58,9 @@ yarn start
<img src="https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*oQQ2RbOzx0oAAAAAAAAAAABkARQnAQ" alt="L7 地理可视化" width = "50%" height = "100%">
现在你可以尽情的本地修改代码,添加自己的图层了。
L7 所有demo都可以在codesandbox 打开,你可以下载代码。

View File

@ -12,7 +12,7 @@ order: 1
<img src="https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*bKT5TrlYlGEAAAAAAAAAAABkARQnAQ" alt="L7 地理可视化" width = "50%" height = "100%">
你可能没有注意,代码区的上方有一排工具按钮,注意了你可能不知道干什么用的
你可能没有注意,代码区的上方有一排工具按钮,。
### 二、打开 codesandbox。
@ -23,7 +23,7 @@ order: 1
<img src="https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*coZsTLbX2FQAAAAAAAAAAABkARQnAQ" alt="L7 地理可视化" width = "50%" height = "100%">
你发现你进入了一个线代码编辑器比较流行,这里面你可以修改代码,并且能够随时看到效果
你发现你进入了一个线代码编辑器,这里面你可以修改代码,并且能够随时看到效果
你可能想说我就想本地跑起来,不想在线修改。

View File

@ -18,7 +18,7 @@ order: 0
2.0版本在L7内部动态引入了高德地图JS API因此不再需要单独引入高德JS API只需设置 type 为 ```amap``` 并且传入token
```html
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
```
### 添加div 标签指定地图容器
@ -106,7 +106,7 @@ fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json')
</head>
<body>
<div id="map"></div>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
<script>
const scene = new L7.Scene({

View File

@ -18,7 +18,7 @@ order: 0
2.0版本在L7内部动态引入了高德地图JS API因此不再需要单独引入高德JS API只需设置 type 为 ```amap``` 并且传入token
```html
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
```
### 添加div 标签指定地图容器
@ -106,7 +106,7 @@ fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json')
</head>
<body>
<div id="map"></div>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
<script>
const scene = new L7.Scene({

View File

@ -24,7 +24,7 @@ order: 0
```html
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
```
@ -118,7 +118,7 @@ fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json')
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js'></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',

View File

@ -24,7 +24,7 @@ order: 0
```html
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
```
@ -116,7 +116,7 @@ fetch('https://gw.alipayobjects.com/os/rmsportal/oVTMqfzuuRFKiDwhPSFL.json')
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js'></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js"></script>
<script>
const scene = new L7.Scene({
id: 'map',

View File

@ -32,7 +32,9 @@ const scene = new Scene({
- 不使用mapbox token
### 如何离线化使用MapBox
你只要不使用MapBox的数据底图服务就可以离线使用mapbox所有数据服务资源都是在style里面配置的。除了数据服务以外还有一些静态资源这些主要是图片标注文字标注的时候使用。<br />mapbox本身资源在国外如果在国内单独部署一套单独使用加载速度体验还是很好的
你只要不使用MapBox的数据底图服务就可以离线使用mapbox所有数据服务资源都是在style里面配置的。除了数据服务以外还有一些静态资源这些主要是图片标注文字标注的时候使用。
mapbox本身数据资源在国外如果在国内单独部署使用加载速度体验还是很好的
我们先了解一下MapBox样式包含哪些配置项。
@ -43,7 +45,9 @@ const scene = new Scene({
- sprite雪碧图将一个地图涉及到的所有零星图标图片都包含到一张大图中。
- glyphs.pbf格式的字体样式例如微软雅黑等字体库。
- sources图层的资源文件可以支持矢量切片、栅格、dem栅格、图片、geojson、视频等格式
- layers是对每个图层样式的描述这里就是对地图样式渲染的关键可以做定制化地图样式。<br />具体参数及其api可以参考mapbox官网
- layers是对每个图层样式的描述这里就是对地图样式渲染的关键可以做定制化地图样式。
具体参数及其api可以参考mapbox官网
如果做到本地化只需要 spriteglyphs 本地化就可以了,地图服务可以加载其他服务。

View File

@ -18,7 +18,7 @@ Include the L7 JS JavaScript <head> of your HTML file.
```html
<head>
<script src='https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js'>
<script src='https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js'>
</script>
</head>
```

View File

@ -15,12 +15,12 @@ Current version: ![L7 2.0版本号](https://badgen.net/npm/v/@antv/l7)
Include the L7 JS JavaScript <head> of your HTML file.
:warning: 如果需要引用第三方地图API请确保在先引入第三方API然后引入L7
⚠️ 如果需要引用第三方地图API请确保在先引入第三方API然后引入L7
```html
<head>
<! --引入第三方地图JSAPI-->
<script src='https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.5/dist/l7.js'>
<script src='https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-2.0.8/dist/l7.js'>
</script>
</head>
```

View File

@ -14,7 +14,7 @@
"message": "chore: publish"
}
},
"version": "2.0.5",
"version": "2.0.11",
"npmClient": "yarn",
"useWorkspaces": true,
"publishConfig": {

View File

@ -103,6 +103,7 @@
"stylelint-config-standard": "^18.2.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.3.2",
"svg-inline-loader": "^0.8.0",
"ts-jest": "^24.0.2",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-component",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -24,8 +24,8 @@
"author": "lzxue",
"license": "ISC",
"dependencies": {
"@antv/l7-core": "^2.0.5",
"@antv/l7-utils": "^2.0.1",
"@antv/l7-core": "^2.0.11",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"eventemitter3": "^4.0.0",
"inversify": "^5.0.1",

View File

@ -1,8 +1,10 @@
import {
IControlOption,
IControlService,
ILayerService,
IMapService,
IRendererService,
PositionName,
TYPES,
} from '@antv/l7-core';
import { DOM } from '@antv/l7-utils';
@ -15,18 +17,12 @@ export enum PositionType {
'BOTTOMRIGHT' = 'bottomright',
'BOTTOMLEFT' = 'bottomleft',
}
export type PositionName =
| 'topright'
| 'topleft'
| 'bottomright'
| 'bottomleft';
export interface IControlOption {
position: PositionName;
[key: string]: any;
}
let controlId = 0;
export default class Control extends EventEmitter {
public controlOption: IControlOption;
protected container: HTMLElement;
protected sceneContainer: Container;
protected mapsService: IMapService;
protected renderService: IRendererService;
protected layerService: ILayerService;
@ -45,18 +41,19 @@ export default class Control extends EventEmitter {
public getDefault() {
return {
position: PositionType.TOPRIGHT,
name: `${controlId++}`,
};
}
public setPosition(position: PositionName) {
// 考虑组件的自动布局,需要销毁重建
// const controlService = this.controlService;
// if (controlService) {
// controlService.removeControl(this);
// }
// this.controlOption.position = position;
// if (controlService) {
// controlService.addControl(this, this.mapsService);
// }
const controlService = this.controlService;
if (controlService) {
controlService.removeControl(this);
}
this.controlOption.position = position;
if (controlService) {
controlService.addControl(this, this.sceneContainer);
}
return this;
}
public addTo(sceneContainer: Container) {
@ -68,7 +65,7 @@ export default class Control extends EventEmitter {
this.controlService = sceneContainer.get<IControlService>(
TYPES.IControlService,
);
this.sceneContainer = sceneContainer;
this.isShow = true;
this.container = this.onAdd();
const container = this.container;

View File

@ -1,10 +1,6 @@
import { IMapService } from '@antv/l7-core';
import { IControlOption, PositionName, PositionType } from '@antv/l7-core';
import { bindAll, DOM, lnglatDistance } from '@antv/l7-utils';
import Control, {
IControlOption,
PositionName,
PositionType,
} from './BaseControl';
import Control from './BaseControl';
export interface ILayerControlOption extends IControlOption {
collapsed: boolean;
autoZIndex: boolean;
@ -55,6 +51,7 @@ export default class Layers extends Control {
autoZIndex: true,
hideSingleBase: false,
sortLayers: false,
name: 'layers',
};
}
public onAdd() {
@ -117,8 +114,6 @@ export default class Layers extends Control {
if (!collapsed) {
this.expand();
}
this.expand();
this.baseLayersList = DOM.create('div', className + '-base', form);
this.separator = DOM.create('div', className + '-separator', form);
this.overlaysList = DOM.create('div', className + '-overlays', form);

View File

@ -1,9 +1,11 @@
import { IControlOption } from '@antv/l7-core';
import { DOM } from '@antv/l7-utils';
import Control, { PositionType } from './BaseControl';
export default class Logo extends Control {
public getDefault() {
return {
position: PositionType.BOTTOMLEFT,
name: 'logo',
};
}
public onAdd() {

View File

@ -1,6 +1,7 @@
import { IMapService } from '@antv/l7-core';
import { IControlOption } from '@antv/l7-core';
import { bindAll, DOM, lnglatDistance } from '@antv/l7-utils';
import Control, { IControlOption, PositionType } from './BaseControl';
import Control, { PositionType } from './BaseControl';
export interface IScaleControlOption extends IControlOption {
maxWidth: number;
metric: boolean;
@ -22,6 +23,7 @@ export default class Scale extends Control {
metric: true,
updateWhenIdle: false,
imperial: false,
name: 'scale',
};
}

View File

@ -1,5 +1,6 @@
import { IControlOption } from '@antv/l7-core';
import { bindAll, DOM } from '@antv/l7-utils';
import Control, { IControlOption, PositionType } from './BaseControl';
import Control, { PositionType } from './BaseControl';
export interface IZoomControlOption extends IControlOption {
zoomInText: string;
zoomInTitle: string;
@ -22,6 +23,7 @@ export default class Zoom extends Control {
zoomInTitle: 'Zoom in',
zoomOutText: '&#x2212;',
zoomOutTitle: 'Zoom out',
name: 'zoom',
};
}

View File

@ -20,6 +20,7 @@ export default class Marker extends EventEmitter {
private mapsService: IMapService<unknown>;
private lngLat: ILngLat;
private scene: Container;
private added: boolean = false;
constructor(option?: Partial<IMarkerOption>) {
super();
this.markerOption = {
@ -49,6 +50,8 @@ export default class Marker extends EventEmitter {
this.registerMarkerEvent(element as HTMLElement);
this.mapsService.on('camerachange', this.update);
this.update();
this.added = true;
this.emit('added');
return this;
}
@ -97,6 +100,55 @@ export default class Marker extends EventEmitter {
return this.markerOption.element as HTMLElement;
}
public setElement(el: HTMLElement): this {
if (!this.added) {
this.once('added', () => {
this.setElement(el);
});
return this;
}
const { element } = this.markerOption;
if (element) {
DOM.remove(element);
}
this.markerOption.element = el;
this.init();
this.mapsService.getMarkerContainer().appendChild(el as HTMLElement);
this.registerMarkerEvent(el as HTMLElement);
this.update();
return this;
}
public openPopup(): this {
if (!this.added) {
this.once('added', () => {
this.openPopup();
});
return this;
}
const popup = this.popup;
if (!popup) {
return this;
}
if (!popup.isOpen()) {
popup.addTo(this.scene);
}
return this;
}
public closePopup(): this {
if (!this.added) {
this.once('added', () => {
this.closePopup();
});
}
const popup = this.popup;
if (popup) {
popup.remove();
}
return this;
}
public setPopup(popup: IPopup) {
this.popup = popup;
if (this.lngLat) {

View File

@ -1,15 +1,17 @@
import { IMapService, IMarker, TYPES } from '@antv/l7-core';
import { bindAll, DOM } from '@antv/l7-utils';
import { bindAll, DOM, Satistics } from '@antv/l7-utils';
import { EventEmitter } from 'eventemitter3';
import { Container } from 'inversify';
import { isFunction } from 'lodash';
import { merge } from 'lodash';
import Supercluster from 'supercluster';
import Marker from './marker';
type CallBack = (...args: any[]) => any;
interface IMarkerStyleOption {
element: CallBack;
element?: CallBack;
style: { [key: string]: any } | CallBack;
className: string;
field?: string;
method?: 'sum' | 'max' | 'min' | 'mean';
radius: number;
maxZoom: number;
minZoom: number;
@ -18,7 +20,7 @@ interface IMarkerStyleOption {
interface IMarkerLayerOption {
cluster: boolean;
clusterOption: IMarkerStyleOption;
clusterOption: Partial<IMarkerStyleOption>;
}
interface IPointFeature {
@ -40,10 +42,7 @@ export default class MarkerLayer extends EventEmitter {
constructor(option?: Partial<IMarkerLayerOption>) {
super();
this.markerLayerOption = {
...this.getDefault(),
...option,
};
this.markerLayerOption = merge(this.getDefault(), option);
bindAll(['update'], this);
this.zoom = this.markerLayerOption.clusterOption?.zoom || -99;
}
@ -57,7 +56,6 @@ export default class MarkerLayer extends EventEmitter {
zoom: -99,
style: {},
className: '',
element: this.generateElement,
},
};
}
@ -77,7 +75,7 @@ export default class MarkerLayer extends EventEmitter {
public addMarker(marker: IMarker) {
const cluster = this.markerLayerOption.cluster;
if (cluster) {
this.addPoint(marker);
this.addPoint(marker, this.markers.length);
}
this.markers.push(marker);
}
@ -113,14 +111,17 @@ export default class MarkerLayer extends EventEmitter {
this.removeAllListeners();
}
private addPoint(marker: IMarker) {
private addPoint(marker: IMarker, id: number) {
const { lng, lat } = marker.getLnglat();
const feature: IPointFeature = {
geometry: {
type: 'Point',
coordinates: [lng, lat],
},
properties: marker.getExtData(),
properties: {
...marker.getExtData(),
marker_id: id,
},
};
this.points.push(feature);
}
@ -152,20 +153,49 @@ export default class MarkerLayer extends EventEmitter {
});
this.clusterMarkers = [];
clusterPoint.forEach((feature) => {
const marker =
feature.properties && feature.properties.hasOwnProperty('point_count')
? this.clusterMarker(feature)
: this.normalMarker(feature);
const { field, method } = this.markerLayerOption.clusterOption;
// 处理聚合数据
if (feature.properties && feature.properties?.cluster_id) {
const clusterData = this.getLeaves(feature.properties?.cluster_id);
feature.properties.clusterData = clusterData;
if (field && method) {
const columnData = clusterData?.map((item) => {
const data = {
[field]: item.properties[field],
};
return data;
});
const column = Satistics.getColumn(columnData as any, field);
const stat = Satistics.getSatByColumn(method, column);
const fieldName = 'point_' + method;
feature.properties[fieldName] = stat;
}
}
const marker = this.clusterMarker(feature);
// feature.properties && feature.properties.hasOwnProperty('point_count')
// ? this.clusterMarker(feature)
// : this.normalMarker(feature);
this.clusterMarkers.push(marker);
marker.addTo(this.scene);
});
}
private getLeaves(
clusterId: number,
limit: number = Infinity,
offset: number = 0,
) {
if (!clusterId) {
return null;
}
return this.clusterIndex.getLeaves(clusterId, limit, offset);
}
private clusterMarker(feature: any) {
const clusterOption = this.markerLayerOption.clusterOption;
const { element } = clusterOption as IMarkerStyleOption;
const {
element = this.generateElement.bind(this),
} = clusterOption as IMarkerStyleOption;
const marker = new Marker({
element: element(feature),
}).setLnglat({
@ -175,11 +205,8 @@ export default class MarkerLayer extends EventEmitter {
return marker;
}
private normalMarker(feature: any) {
const marker = new Marker().setLnglat({
lng: feature.geometry.coordinates[0],
lat: feature.geometry.coordinates[1],
});
return marker;
const marker_id = feature.properties.marker_id;
return this.markers[marker_id];
}
private update() {
@ -199,11 +226,14 @@ export default class MarkerLayer extends EventEmitter {
const el = DOM.create('div', 'l7-marker-cluster');
const label = DOM.create('div', '', el);
const span = DOM.create('span', '', label);
span.textContent = feature.properties.point_count;
// if (className !== '') {
// DOM.addClass(el, className);
// }
// span.textContent = feature.properties.point_count;
const { field, method } = this.markerLayerOption.clusterOption;
feature.properties.point_count = feature.properties.point_count || 1;
const text =
field && method
? feature.properties['point_' + method] || feature.properties[field]
: feature.properties.point_count;
span.textContent = text;
// const elStyle = isFunction(style)
// ? style(feature.properties.point_count)
// : style;

View File

@ -23,6 +23,7 @@ export default class Popup extends EventEmitter implements IPopup {
private timeoutInstance: any;
private container: HTMLElement;
private tip: HTMLElement;
private scene: Container;
constructor(cfg?: Partial<IPopupOption>) {
super();
@ -36,15 +37,25 @@ export default class Popup extends EventEmitter implements IPopup {
public addTo(scene: Container) {
this.mapsService = scene.get<IMapService>(TYPES.IMapService);
this.mapsService.on('camerachange', this.update);
this.scene = scene;
this.update();
if (this.popupOption.closeOnClick) {
this.timeoutInstance = setTimeout(() => {
this.mapsService.on('click', this.onClickClose);
}, 30);
}
this.emit('open');
return this;
}
public close(): void {
this.remove();
}
public open(): void {
this.addTo(this.scene);
}
public setHTML(html: string) {
const frag = window.document.createDocumentFragment();
const temp = window.document.createElement('body');

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-core",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -22,7 +22,7 @@
"author": "xiaoiver",
"license": "ISC",
"dependencies": {
"@antv/l7-utils": "^2.0.1",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"@mapbox/tiny-sdf": "^1.1.1",
"ajv": "^6.10.2",

View File

@ -73,10 +73,10 @@ container
.bind<IGlobalConfigService>(TYPES.IGlobalConfigService)
.to(GlobalConfigService)
.inSingletonScope();
container
.bind<IIconService>(TYPES.IIconService)
.to(IconService)
.inSingletonScope();
// container
// .bind<IIconService>(TYPES.IIconService)
// .to(IconService)
// .inSingletonScope();
container
.bind<IShaderModuleService>(TYPES.IShaderModuleService)
.to(ShaderModuleService)
@ -85,10 +85,10 @@ container
.bind<ILogService>(TYPES.ILogService)
.to(LogService)
.inSingletonScope();
container
.bind<IFontService>(TYPES.IFontService)
.to(FontService)
.inSingletonScope();
// container
// .bind<IFontService>(TYPES.IFontService)
// .to(FontService)
// .inSingletonScope();
// @see https://github.com/inversify/InversifyJS/blob/master/wiki/inheritance.md#what-can-i-do-when-my-base-class-is-provided-by-a-third-party-module
decorate(injectable(), EventEmitter);
@ -160,7 +160,6 @@ export function createSceneContainer() {
sceneContainer
.bind<string>(TYPES.SceneID)
.toConstantValue(`${sceneIdCounter++}`);
sceneContainer
.bind<ILayerService>(TYPES.ILayerService)
.to(LayerService)
@ -189,6 +188,14 @@ export function createSceneContainer() {
.bind<IMarkerService>(TYPES.IMarkerService)
.to(MarkerService)
.inSingletonScope();
sceneContainer
.bind<IIconService>(TYPES.IIconService)
.to(IconService)
.inSingletonScope();
sceneContainer
.bind<IFontService>(TYPES.IFontService)
.to(FontService)
.inSingletonScope();
sceneContainer
.bind<IPopupService>(TYPES.IPopupService)

View File

@ -32,6 +32,11 @@ export default class ControlService implements IControlService {
this.unAddControls.push(ctr);
}
}
public getControlByName(name: string | number): IControl | undefined {
return this.controls.find((ctr) => {
return ctr.controlOption.name === name;
});
}
public removeControl(ctr: IControl): this {
const index = this.controls.indexOf(ctr);
if (index > -1) {

View File

@ -5,8 +5,16 @@ export enum PositionType {
'BOTTOMRIGHT' = 'bottomright',
'BOTTOMLEFT' = 'bottomleft',
}
export type PositionName =
| 'topright'
| 'topleft'
| 'bottomright'
| 'bottomleft';
export interface IControlOption {
position: PositionType;
name: string;
position: PositionName;
[key: string]: any;
}
export interface IControlServiceCfg {
container: HTMLElement;
@ -15,6 +23,7 @@ export interface IControlCorners {
[key: string]: HTMLElement;
}
export interface IControl {
controlOption: IControlOption;
setPosition(pos: PositionType): void;
addTo(sceneContainer: Container): void;
onAdd(): HTMLElement;
@ -29,6 +38,7 @@ export interface IControlService {
addControls(): void;
init(cfg: IControlServiceCfg, sceneContainer: Container): void;
addControl(ctr: IControl, sceneContainer: Container): void;
getControlByName(name: string | number): IControl | undefined;
removeControl(ctr: IControl): void;
destroy(): void;
}

View File

@ -19,6 +19,9 @@ export interface IMarker {
setExtData(data: any): void;
setPopup(popup: IPopup): void;
togglePopup(): this;
openPopup(): this;
closePopup(): this;
setElement(el: HTMLElement): this;
}
export interface IMarkerService {
container: HTMLElement;

View File

@ -10,10 +10,13 @@ export interface IPopup {
setText(text: string): this;
setMaxWidth(maxWidth: string): this;
isOpen(): boolean;
open(): void;
close(): void;
}
export interface IPopupService {
addPopup(popup: IPopup): void;
removePopup(popup: IPopup): void;
init(scene: Container): void;
initPopup(): void;
destroy(): void;
}

View File

@ -7,6 +7,8 @@ import { IPopup, IPopupService } from './IPopupService';
export default class PopupService implements IPopupService {
private scene: Container;
private popup: IPopup;
private mapsService: IMapService;
private unAddPopup: IPopup | null;
public removePopup(popup: IPopup): void {
popup.remove();
@ -20,11 +22,22 @@ export default class PopupService implements IPopupService {
if (this.popup) {
this.popup.remove();
}
popup.addTo(this.scene);
this.popup = popup;
if (this.mapsService.map && this.mapsService.getMarkerContainer()) {
popup.addTo(this.scene);
this.popup = popup;
} else {
this.unAddPopup = popup;
}
}
public initPopup() {
if (this.unAddPopup) {
this.addPopup(this.unAddPopup);
this.unAddPopup = null;
}
}
public init(scene: Container) {
this.scene = scene;
this.mapsService = scene.get<IMapService>(TYPES.IMapService);
}
}

View File

@ -20,6 +20,12 @@ export default class InteractionService extends EventEmitter
private hammertime: HammerManager;
private lastClickTime: number = 0;
private lastClickXY: number[] = [-1, -1];
private clickTimer: number;
public init() {
// 注册事件在地图底图上
this.addEventListenerOnMap();
@ -59,7 +65,7 @@ export default class InteractionService extends EventEmitter
$containter.addEventListener('click', this.onHover);
$containter.addEventListener('mousedown', this.onHover);
$containter.addEventListener('mouseup', this.onHover);
$containter.addEventListener('dblclick', this.onHover);
// $containter.addEventListener('dblclick', this.onHover);
$containter.addEventListener('contextmenu', this.onHover);
this.hammertime = hammertime;
@ -75,7 +81,7 @@ export default class InteractionService extends EventEmitter
$containter.removeEventListener('click', this.onHover);
$containter.removeEventListener('mousedown', this.onHover);
$containter.removeEventListener('mouseup', this.onHover);
$containter.removeEventListener('dblclick', this.onHover);
// $containter.removeEventListener('dblclick', this.onHover);
$containter.removeEventListener('contextmenu', this.onHover);
}
}
@ -88,6 +94,32 @@ export default class InteractionService extends EventEmitter
y -= top;
}
const lngLat = this.mapService.containerToLngLat([x, y]);
if (type === 'click') {
const nowTime = new Date().getTime();
if (
nowTime - this.lastClickTime < 500 &&
Math.abs(this.lastClickXY[0] - x) < 10 &&
Math.abs(this.lastClickXY[1] - y) < 10
) {
this.lastClickTime = 0;
this.lastClickXY = [-1, -1];
if (this.clickTimer) {
clearTimeout(this.clickTimer);
}
type = 'dblclick';
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
} else {
this.lastClickTime = nowTime;
this.lastClickXY = [x, y];
this.clickTimer = setTimeout(() => {
type = 'click';
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
}, 500);
}
return;
}
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
};
}

View File

@ -27,9 +27,9 @@ export default class LayerService implements ILayerService {
private readonly configService: IGlobalConfigService;
public add(layer: ILayer) {
// if (this.sceneInited) {
// layer.init();
// }
if (this.sceneInited) {
layer.init();
}
this.layers.push(layer);
}
@ -73,6 +73,7 @@ export default class LayerService implements ILayerService {
this.alreadyInRendering = true;
this.clear();
this.layers
.filter((layer) => layer.inited)
.filter((layer) => layer.isVisible())
.forEach((layer) => {
// trigger hooks

View File

@ -205,10 +205,17 @@ export default class StyleAttributeService implements IStyleAttributeService {
normals: normalsForCurrentFeature,
size: vertexSize,
} = this.triangulation(feature);
indices.push(...indicesForCurrentFeature.map((i) => i + verticesNum));
vertices.push(...verticesForCurrentFeature);
indicesForCurrentFeature.forEach((i) => {
indices.push(i + verticesNum);
});
verticesForCurrentFeature.forEach((index) => {
vertices.push(index);
});
// fix Maximum call stack size exceeded https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why
if (normalsForCurrentFeature) {
normals.push(...normalsForCurrentFeature);
normalsForCurrentFeature.forEach((normal) => {
normals.push(normal);
});
}
size = vertexSize;
const verticesNumForCurrentFeature =

View File

@ -58,4 +58,5 @@ export interface IMultiPassRenderer {
getRenderFlag(): boolean;
setRenderFlag(enabled: boolean): void;
setLayer(layer: ILayer): void;
destroy(): void;
}

View File

@ -82,4 +82,8 @@ export default class MultiPassRenderer implements IMultiPassRenderer {
pass.init(this.layer, config);
this.passes.splice(index, 0, pass);
}
public destroy() {
this.passes.length = 0;
}
}

View File

@ -34,6 +34,10 @@ export default class PixelPickingPass<
*/
private layer: ILayer;
private width: number = 0;
private height: number = 0;
/**
* throttle hover picking framebuffer
*/
@ -91,8 +95,11 @@ export default class PixelPickingPass<
this.alreadyInRendering = true;
// resize first, fbo can't be resized in use
this.pickingFBO.resize({ width, height });
if (this.width !== width || this.height !== height) {
this.pickingFBO.resize({ width, height });
this.width = width;
this.height = height;
}
useFramebuffer(this.pickingFBO, () => {
clear({
framebuffer: this.pickingFBO,

View File

@ -10,6 +10,7 @@ import { IIconService } from '../asset/IIconService';
import { ICameraService, IViewport } from '../camera/ICameraService';
import { IControlService } from '../component/IControlService';
import { IMarkerService } from '../component/IMarkerService';
import { IPopupService } from '../component/IPopupService';
import { IGlobalConfigService, ISceneConfig } from '../config/IConfigService';
import { ICoordinateSystemService } from '../coordinate/ICoordinateSystemService';
import { IInteractionService } from '../interaction/IInteractionService';
@ -69,6 +70,9 @@ export default class Scene extends EventEmitter implements ISceneService {
@inject(TYPES.IMarkerService)
private readonly markerService: IMarkerService;
@inject(TYPES.IPopupService)
private readonly popupService: IPopupService;
/**
*
*/
@ -139,9 +143,11 @@ export default class Scene extends EventEmitter implements ISceneService {
// 重新绑定非首次相机更新事件
this.map.onCameraChanged(this.handleMapCameraChanged);
this.map.addMarkerContainer();
// 初始化未加载的marker;
this.markerService.addMarkers();
this.markerService.addMarkerLayers();
this.popupService.initPopup();
// 地图初始化之后 才能初始化 container 上的交互
this.interactionService.init();
this.logger.debug(`map ${this.id} loaded`);
@ -201,13 +207,13 @@ export default class Scene extends EventEmitter implements ISceneService {
// FIXME: 初始化 marker 容器,可以放到 map 初始化方法中?
this.logger.info(' render inited');
this.layerService.initLayers();
this.controlService.addControls();
this.emit('loaded');
this.inited = true;
}
// 尝试初始化未初始化的图层
this.layerService.initLayers();
this.layerService.renderLayers();
// 组件需要等待layer 初始化完成之后添加

View File

@ -16,11 +16,11 @@ vec4 filterHighlightColor(vec4 color) {
if (selected) {
vec4 highLightColor = u_HighlightColor * COLOR_SCALE;
float highLightAlpha = highLightColor.a;
float highLightRatio = highLightAlpha / (highLightAlpha + color.a * (1.0 - highLightAlpha));
// float highLightAlpha = highLightColor.a;
// float highLightRatio = highLightAlpha / (highLightAlpha + color.a * (1.0 - highLightAlpha));
vec3 resultRGB = mix(color.rgb, highLightColor.rgb, highLightRatio);
return vec4(resultRGB, color.a);
// vec3 resultRGB = mix(color.rgb, highLightColor.rgb, highLightRatio);
return highLightColor;
} else {
return color;
}

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7",
"version": "2.0.5",
"version": "2.0.11",
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
"main": "lib/index.js",
"module": "es/index.js",
@ -24,11 +24,11 @@
"author": "antv",
"license": "MIT",
"dependencies": {
"@antv/l7-component": "^2.0.5",
"@antv/l7-core": "^2.0.5",
"@antv/l7-layers": "^2.0.5",
"@antv/l7-maps": "^2.0.5",
"@antv/l7-scene": "^2.0.5",
"@antv/l7-component": "^2.0.11",
"@antv/l7-core": "^2.0.11",
"@antv/l7-layers": "^2.0.11",
"@antv/l7-maps": "^2.0.11",
"@antv/l7-scene": "^2.0.11",
"@babel/runtime": "^7.7.7"
},
"gitHead": "9fabb78790428d2025b89fb6146fc555cb1d987d",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-layers",
"version": "2.0.5",
"version": "2.0.11",
"description": "L7's collection of built-in layers",
"main": "lib/index.js",
"module": "es/index.js",
@ -22,9 +22,9 @@
"author": "xiaoiver",
"license": "ISC",
"dependencies": {
"@antv/l7-core": "^2.0.5",
"@antv/l7-source": "^2.0.5",
"@antv/l7-utils": "^2.0.1",
"@antv/l7-core": "^2.0.11",
"@antv/l7-source": "^2.0.11",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"@mapbox/martini": "^0.1.0",
"@turf/meta": "^6.0.2",

View File

@ -56,7 +56,7 @@ let layerIdCounter = 0;
export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
implements ILayer {
public id: string = `${layerIdCounter++}`;
public name: string = `${layerIdCounter++}`;
public name: string = `${layerIdCounter}`;
public type: string;
public visible: boolean = true;
public zIndex: number = 0;
@ -230,10 +230,11 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
this.configService.setLayerConfig(sceneId, this.id, {});
// 全局容器服务
// 场景容器服务
this.iconService = this.container.get<IIconService>(TYPES.IIconService);
this.fontService = this.container.get<IFontService>(TYPES.IFontService);
// 场景容器服务
this.rendererService = this.container.get<IRendererService>(
TYPES.IRendererService,
);
@ -658,6 +659,8 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
// 清除sources事件
this.layerSource.off('update', this.sourceEvent);
this.multiPassRenderer.destroy();
// 清除所有属性以及关联的 vao
this.styleAttributeService.clearAllAttributes();
// 销毁所有 model

View File

@ -32,16 +32,18 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
@lazyInject(TYPES.IGlobalConfigService)
protected readonly configService: IGlobalConfigService;
@lazyInject(TYPES.IIconService)
protected readonly iconService: IIconService;
// @lazyInject(TYPES.IIconService)
// protected readonly iconService: IIconService;
@lazyInject(TYPES.IFontService)
protected readonly fontService: IFontService;
// @lazyInject(TYPES.IFontService)
// protected readonly fontService: IFontService;
@lazyInject(TYPES.IShaderModuleService)
protected readonly shaderModuleService: IShaderModuleService;
protected rendererService: IRendererService;
protected iconService: IIconService;
protected fontService: IFontService;
protected styleAttributeService: IStyleAttributeService;
protected mapService: IMapService;
protected cameraService: ICameraService;
@ -56,6 +58,12 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
.getContainer()
.get<IStyleAttributeService>(TYPES.IStyleAttributeService);
this.mapService = layer.getContainer().get<IMapService>(TYPES.IMapService);
this.iconService = layer
.getContainer()
.get<IIconService>(TYPES.IIconService);
this.fontService = layer
.getContainer()
.get<IFontService>(TYPES.IFontService);
this.cameraService = layer
.getContainer()
.get<ICameraService>(TYPES.ICameraService);

View File

@ -106,6 +106,8 @@ export default class ImageModel extends BaseModel {
const { createTexture2D } = this.rendererService;
this.texture = createTexture2D({
data: this.iconService.getCanvas(),
mag: gl.LINEAR,
min: gl.LINEAR,
width: 1024,
height: this.iconService.canvasHeight || 128,
});

View File

@ -92,6 +92,7 @@ export default class TextModel extends BaseModel {
stroke = '#fff',
strokeWidth = 0,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
this.updateTexture();
const { canvas } = this.fontService;
return {
u_opacity: 1.0,
@ -104,6 +105,7 @@ export default class TextModel extends BaseModel {
}
public buildModels(): IModel[] {
this.extent = this.textExtent();
this.initGlyph();
this.updateTexture();
this.filterGlyphs();

View File

@ -9,6 +9,7 @@ uniform float u_stroke_opacity : 1;
uniform float u_opacity : 1;
varying float v_size;
#pragma include "picking"
void main(){
vec2 pos= v_uv / u_textSize + gl_PointCoord / u_textSize * 64.;
vec2 fragmentPosition = 2.0*gl_PointCoord - 1.0;
@ -24,5 +25,5 @@ float r = 1.0 - smoothstep(radius-(radius*0.01),
}else {
gl_FragColor= step(0.01, textureColor.x) * v_color;
}
return;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -11,6 +11,7 @@ uniform float u_stroke_width : 1;
varying float v_size;
#pragma include "projection"
#pragma include "picking"
void main() {
v_color = a_Color;
@ -20,5 +21,6 @@ void main() {
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0));
gl_PointSize = a_Size * 2.0 * u_DevicePixelRatio;
setPickingColor(a_PickingColor);
}

View File

@ -13,6 +13,7 @@ varying vec4 v_color;
varying vec2 v_uv;
varying float v_gamma_scale;
#pragma include "picking"
void main() {
// get sdf from atlas
float dist = texture2D(u_sdf_map, v_uv).a;
@ -27,4 +28,5 @@ void main() {
highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
gl_FragColor = mix(v_color * u_opacity, u_stroke, smoothstep(0., 0.5, 1. - dist)) * alpha;
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -14,6 +14,7 @@ varying float v_gamma_scale;
varying vec4 v_color;
#pragma include "projection"
#pragma include "picking"
void main() {
v_color = a_Color;
@ -29,6 +30,6 @@ void main() {
gl_Position = vec4(projected_position.xy / projected_position.w
+ a_textOffsets * fontScale / u_ViewportSize * 2. * u_DevicePixelRatio, 0.0, 1.0);
v_gamma_scale = gl_Position.w;
setPickingColor(a_PickingColor);
}

View File

@ -217,7 +217,7 @@ export default function(
pickData.push(
attrPos[i * 3],
attrPos[i * 3 + 1],
attrPos[i * 3 + 1],
attrPos[i * 3 + 2],
attrDistance[i],
miters[i],
totalDistance,

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-maps",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -23,8 +23,8 @@
"author": "xiaoiver",
"license": "ISC",
"dependencies": {
"@antv/l7-core": "^2.0.5",
"@antv/l7-utils": "^2.0.1",
"@antv/l7-core": "^2.0.11",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"gl-matrix": "^3.1.0",
"inversify": "^5.0.1",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-renderer",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -25,7 +25,7 @@
"gl": "^4.4.0"
},
"dependencies": {
"@antv/l7-core": "^2.0.5",
"@antv/l7-core": "^2.0.11",
"@babel/runtime": "^7.7.7",
"inversify": "^5.0.1",
"lodash": "^4.17.15",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-scene",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -22,11 +22,11 @@
"author": "xiaoiver",
"license": "ISC",
"dependencies": {
"@antv/l7-component": "^2.0.5",
"@antv/l7-core": "^2.0.5",
"@antv/l7-maps": "^2.0.5",
"@antv/l7-renderer": "^2.0.5",
"@antv/l7-utils": "^2.0.1",
"@antv/l7-component": "^2.0.11",
"@antv/l7-core": "^2.0.11",
"@antv/l7-maps": "^2.0.11",
"@antv/l7-renderer": "^2.0.11",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"inversify": "^5.0.1",
"mapbox-gl": "^1.2.1",

View File

@ -158,6 +158,10 @@ class Scene
this.controlService.removeControl(ctr);
}
public getControlByName(name: string) {
return this.controlService.getControlByName(name);
}
// marker
public addMarker(marker: IMarker) {
this.markerService.addMarker(marker);

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-source",
"version": "2.0.5",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -24,8 +24,8 @@
"author": "lzxue",
"license": "ISC",
"dependencies": {
"@antv/l7-core": "^2.0.5",
"@antv/l7-utils": "^2.0.1",
"@antv/l7-core": "^2.0.11",
"@antv/l7-utils": "^2.0.11",
"@babel/runtime": "^7.7.7",
"@mapbox/geojson-rewind": "^0.4.0",
"@turf/helpers": "^6.1.4",

View File

@ -137,8 +137,9 @@ export default class Source extends EventEmitter {
public getFeatureById(id: number): unknown {
const { type = 'geojson' } = this.parser;
if (type === 'geojson' && !this.cluster) {
return id < this.rawData.features.length
? this.rawData.features[id]
// TODO 聚合图层返回聚合和后的数据
return id < this.originData.features.length
? this.originData.features[id]
: 'null';
} else {
return id < this.data.dataArray.length ? this.data.dataArray[id] : 'null';

View File

@ -1,9 +1,8 @@
/**
*
*/
import { IParserCfg, IParserData, ISourceCFG, ITransform } from '@antv/l7-core';
import { aProjectFlat, metersToLngLat } from '@antv/l7-utils';
import { statMap } from './statistics';
import { IParserData, ITransform } from '@antv/l7-core';
import { Satistics } from '@antv/l7-utils';
interface IGridHash {
[key: string]: any;
@ -90,8 +89,8 @@ function _getGridLayerDataFromGridHash(
[key: string]: any;
} = {};
if (option.field && option.method) {
const columns = getColumn(gridHash[key].points, option.field);
item[option.method] = statMap[option.method](columns);
const columns = Satistics.getColumn(gridHash[key].points, option.field);
item[option.method] = Satistics.statMap[option.method](columns);
}
Object.assign(item, {
_id: i + 1,
@ -99,6 +98,7 @@ function _getGridLayerDataFromGridHash(
-180 + gridOffset.xOffset * lonIdx,
-90 + gridOffset.yOffset * latIdx,
],
rawData: gridHash[key].points,
count: gridHash[key].count,
});
// @ts-ignore
@ -106,8 +106,3 @@ function _getGridLayerDataFromGridHash(
return accu;
}, []);
}
function getColumn(data: any[], columnName: string) {
return data.map((item) => {
return item[columnName] * 1;
});
}

View File

@ -1,94 +0,0 @@
/**
*
*/
import {
IParseDataItem,
IParserCfg,
IParserData,
ISourceCFG,
ITransform,
} from '@antv/l7-core';
import { aProjectFlat, metersToLngLat } from '@antv/l7-utils';
import { statMap } from './statistics';
interface IGridHash {
[key: string]: any;
}
interface IGridOffset {
yOffset: number;
xOffset: number;
}
interface IRawData {
coordinates: [number, number];
[key: string]: any;
}
const R_EARTH = 6378000;
export function aggregatorToGrid(data: IParserData, option: ITransform) {
const dataArray = data.dataArray;
const { size = 10 } = option;
const pixlSize = ((size / (2 * Math.PI * R_EARTH)) * (256 << 20)) / 2;
const screenPoints: IRawData[] = dataArray.map((point: IParseDataItem) => {
const [x, y] = aProjectFlat(point.coordinates);
return {
...point,
coordinates: [parseInt(x.toFixed(0), 10), parseInt(y.toFixed(0), 10)],
};
});
const gridHash = _pointsGridHash(screenPoints, pixlSize);
const layerData = _getGridLayerDataFromGridHash(gridHash, pixlSize, option);
return {
yOffset: pixlSize / 2,
xOffset: pixlSize / 2,
dataArray: layerData,
};
}
function _pointsGridHash(dataArray: any[], size: number) {
const gridHash: IGridHash = {};
for (const point of dataArray) {
const x = point.coordinates[0];
const y = point.coordinates[1];
const latIdx = Math.floor(y / size);
const lonIdx = Math.floor(x / size);
const key = `${latIdx}-${lonIdx}`;
gridHash[key] = gridHash[key] || { count: 0, points: [] };
gridHash[key].count += 1;
gridHash[key].points.push(point);
}
return gridHash;
}
function _getGridLayerDataFromGridHash(
gridHash: IGridHash,
size: number,
option: ITransform,
) {
return Object.keys(gridHash).reduce((accu, key, i) => {
const idxs = key.split('-');
const latIdx = parseInt(idxs[0], 10);
const lonIdx = parseInt(idxs[1], 10);
const item: {
[key: string]: any;
} = {};
if (option.field && option.method) {
const columns = getColumn(gridHash[key].points, option.field);
item[option.method] = statMap[option.method](columns);
}
Object.assign(item, {
_id: i + 1,
coordinates: [lonIdx * size, latIdx * size],
count: gridHash[key].count,
});
// @ts-ignore
accu.push(item);
return accu;
}, []);
}
function getColumn(data: any[], columnName: string) {
return data.map((item) => {
return item[columnName] * 1;
});
}

View File

@ -1,14 +1,12 @@
import { aProjectFlat, metersToLngLat } from '@antv/l7-utils';
import { aProjectFlat, Satistics } from '@antv/l7-utils';
import { hexbin } from 'd3-hexbin';
const R_EARTH = 6378000;
import {
IParseDataItem,
IParserCfg,
IParserData,
ISourceCFG,
ITransform,
} from '@antv/l7-core';
import { statMap } from './statistics';
interface IHexBinItem<T> extends Array<T> {
x: number;
y: number;
@ -20,7 +18,7 @@ interface IRawData {
}
export function pointToHexbin(data: IParserData, option: ITransform) {
const dataArray = data.dataArray;
const { size = 10 } = option;
const { size = 10, method = 'sum' } = option;
const pixlSize = ((size / (2 * Math.PI * R_EARTH)) * (256 << 20)) / 2;
const screenPoints: IRawData[] = dataArray.map((point: IParseDataItem) => {
const [x, y] = aProjectFlat(point.coordinates);
@ -38,13 +36,14 @@ export function pointToHexbin(data: IParserData, option: ITransform) {
const result: IParserData = {
dataArray: hexbinBins.map((hex: IHexBinItem<IRawData>, index: number) => {
if (option.field && option.method) {
const columns = getColumn(hex, option.field);
hex[option.method] = statMap[option.method](columns);
if (option.field && method) {
const columns = Satistics.getColumn(hex, option.field);
hex[method] = Satistics.statMap[method](columns);
}
return {
[option.method]: hex[option.method],
[option.method]: hex[method],
count: hex.length,
rawData: hex,
coordinates: [hex.x, hex.y],
_id: index + 1,
};
@ -56,8 +55,3 @@ export function pointToHexbin(data: IParserData, option: ITransform) {
};
return result;
}
function getColumn(data: IHexBinItem<IRawData>, columnName: string) {
return data.map((item: IRawData) => {
return item[columnName] * 1;
});
}

View File

@ -14,7 +14,7 @@ export function join(geoData: IParserData, options: { [key: string]: any }) {
const { field, data } = options;
const dataObj: { [key: string]: any } = {};
data.forEach((element: { [key: string]: any }) => {
dataObj[element.field] = element;
dataObj[element[field]] = element;
});
geoData.dataArray = data.dataArray.map((item: IParseDataItem) => {
const joinName = item[field];

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-utils",
"version": "2.0.1",
"version": "2.0.11",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -142,3 +142,13 @@ export function triggerResize() {
window.dispatchEvent(evt);
}
}
export function printCanvas(canvas: HTMLCanvasElement) {
const css = [
'padding: ' + (canvas.height / 2 - 8) + 'px ' + canvas.width / 2 + 'px;',
'line-height: ' + canvas.height + 'px;',
'background-image: url(' + canvas.toDataURL() + ');',
];
// tslint:disable-next-line:no-console
console.log('%c\n', css.join(''));
}

View File

@ -5,4 +5,5 @@ export * from './geo';
export * from './lru_cache';
export * from './event';
export * from './color';
export { DOM };
import * as Satistics from './statistics';
export { DOM, Satistics };

View File

@ -1,3 +1,6 @@
interface IItemData {
[key: string]: any;
}
function max(x: number[]) {
if (x.length === 0) {
throw new Error('max requires at least one data point');
@ -75,3 +78,12 @@ export const statMap: { [key: string]: any } = {
mean,
sum,
};
export function getColumn(data: IItemData[], columnName: string) {
return data.map((item: IItemData) => {
return item[columnName] * 1;
});
}
export function getSatByColumn(type: string, column: number[]) {
return statMap[type](column);
}

Some files were not shown because too many files have changed in this diff Show More