mirror of https://gitee.com/antv-l7/antv-l7
commit
8037318094
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: Marker Layer
|
title: Marker 图层
|
||||||
order: 3
|
order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -33,11 +33,20 @@ scene.addMarkerLayer(markerLayer);
|
||||||
|
|
||||||
#### option
|
#### option
|
||||||
|
|
||||||
- cluster 是部分聚合 `boolean` 默认 `false`
|
- cluster 聚合 `boolean` 默认 `false`
|
||||||
|
|
||||||
- clusterOption 聚合配置
|
- 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
|
添加 Marker
|
||||||
|
|
||||||
|
@ -58,6 +67,21 @@ const marker = new Marker().setLnglat(); // 添加进Marker必须设置经纬度
|
||||||
markerLayer.addMarker(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
|
#### removeMarker
|
||||||
|
|
||||||
从 MarkerLayer 移除 Marker
|
从 MarkerLayer 移除 Marker
|
||||||
|
|
|
@ -36,7 +36,17 @@ scene.addMarkerLayer(markerLayer);
|
||||||
- cluster 聚合 `boolean` 默认 `false`
|
- cluster 聚合 `boolean` 默认 `false`
|
||||||
|
|
||||||
- clusterOption 聚合配置
|
- clusterOption 聚合配置
|
||||||
|
|
||||||
|
- field `string` 聚合统计字段
|
||||||
|
- method `sum| max| min| mean`
|
||||||
- element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素
|
- 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 计算
|
||||||
|
|
||||||
后续会增加更多配置项目
|
后续会增加更多配置项目
|
||||||
|
|
||||||
|
@ -57,6 +67,21 @@ const marker = new Marker().setLnglat(); // 添加进Marker必须设置经纬度
|
||||||
markerLayer.addMarker(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
|
#### removeMarker
|
||||||
|
|
||||||
从 MarkerLayer 移除 Marker
|
从 MarkerLayer 移除 Marker
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"message": "chore: publish"
|
"message": "chore: publish"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-component",
|
"name": "@antv/l7-component",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
"author": "lzxue",
|
"author": "lzxue",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"eventemitter3": "^4.0.0",
|
"eventemitter3": "^4.0.0",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { IMapService, IMarker, TYPES } from '@antv/l7-core';
|
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 { EventEmitter } from 'eventemitter3';
|
||||||
import { Container } from 'inversify';
|
import { Container } from 'inversify';
|
||||||
import { isFunction } from 'lodash';
|
import { merge } from 'lodash';
|
||||||
import Supercluster from 'supercluster';
|
import Supercluster from 'supercluster';
|
||||||
import Marker from './marker';
|
import Marker from './marker';
|
||||||
type CallBack = (...args: any[]) => any;
|
type CallBack = (...args: any[]) => any;
|
||||||
|
@ -10,6 +10,8 @@ interface IMarkerStyleOption {
|
||||||
element: CallBack;
|
element: CallBack;
|
||||||
style: { [key: string]: any } | CallBack;
|
style: { [key: string]: any } | CallBack;
|
||||||
className: string;
|
className: string;
|
||||||
|
field?: string;
|
||||||
|
method?: 'sum' | 'max' | 'min' | 'mean';
|
||||||
radius: number;
|
radius: number;
|
||||||
maxZoom: number;
|
maxZoom: number;
|
||||||
minZoom: number;
|
minZoom: number;
|
||||||
|
@ -18,7 +20,7 @@ interface IMarkerStyleOption {
|
||||||
|
|
||||||
interface IMarkerLayerOption {
|
interface IMarkerLayerOption {
|
||||||
cluster: boolean;
|
cluster: boolean;
|
||||||
clusterOption: IMarkerStyleOption;
|
clusterOption: Partial<IMarkerStyleOption>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPointFeature {
|
interface IPointFeature {
|
||||||
|
@ -40,10 +42,7 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
|
|
||||||
constructor(option?: Partial<IMarkerLayerOption>) {
|
constructor(option?: Partial<IMarkerLayerOption>) {
|
||||||
super();
|
super();
|
||||||
this.markerLayerOption = {
|
this.markerLayerOption = merge(this.getDefault(), option);
|
||||||
...this.getDefault(),
|
|
||||||
...option,
|
|
||||||
};
|
|
||||||
bindAll(['update'], this);
|
bindAll(['update'], this);
|
||||||
this.zoom = this.markerLayerOption.clusterOption?.zoom || -99;
|
this.zoom = this.markerLayerOption.clusterOption?.zoom || -99;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +76,7 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
public addMarker(marker: IMarker) {
|
public addMarker(marker: IMarker) {
|
||||||
const cluster = this.markerLayerOption.cluster;
|
const cluster = this.markerLayerOption.cluster;
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
this.addPoint(marker);
|
this.addPoint(marker, this.markers.length);
|
||||||
}
|
}
|
||||||
this.markers.push(marker);
|
this.markers.push(marker);
|
||||||
}
|
}
|
||||||
|
@ -114,14 +113,17 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
this.removeAllListeners();
|
this.removeAllListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
private addPoint(marker: IMarker) {
|
private addPoint(marker: IMarker, id: number) {
|
||||||
const { lng, lat } = marker.getLnglat();
|
const { lng, lat } = marker.getLnglat();
|
||||||
const feature: IPointFeature = {
|
const feature: IPointFeature = {
|
||||||
geometry: {
|
geometry: {
|
||||||
type: 'Point',
|
type: 'Point',
|
||||||
coordinates: [lng, lat],
|
coordinates: [lng, lat],
|
||||||
},
|
},
|
||||||
properties: marker.getExtData(),
|
properties: {
|
||||||
|
...marker.getExtData(),
|
||||||
|
marker_id: id,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
this.points.push(feature);
|
this.points.push(feature);
|
||||||
}
|
}
|
||||||
|
@ -151,6 +153,24 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
});
|
});
|
||||||
this.clusterMarkers = [];
|
this.clusterMarkers = [];
|
||||||
clusterPoint.forEach((feature) => {
|
clusterPoint.forEach((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 =
|
const marker =
|
||||||
feature.properties && feature.properties.hasOwnProperty('point_count')
|
feature.properties && feature.properties.hasOwnProperty('point_count')
|
||||||
? this.clusterMarker(feature)
|
? this.clusterMarker(feature)
|
||||||
|
@ -160,7 +180,16 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
marker.addTo(this.scene);
|
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) {
|
private clusterMarker(feature: any) {
|
||||||
const clusterOption = this.markerLayerOption.clusterOption;
|
const clusterOption = this.markerLayerOption.clusterOption;
|
||||||
|
|
||||||
|
@ -174,11 +203,13 @@ export default class MarkerLayer extends EventEmitter {
|
||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
private normalMarker(feature: any) {
|
private normalMarker(feature: any) {
|
||||||
const marker = new Marker().setLnglat({
|
const marker_id = feature.properties.marker_id;
|
||||||
lng: feature.geometry.coordinates[0],
|
return marker_id
|
||||||
lat: feature.geometry.coordinates[1],
|
? new Marker().setLnglat({
|
||||||
});
|
lng: feature.geometry.coordinates[0],
|
||||||
return marker;
|
lat: feature.geometry.coordinates[1],
|
||||||
|
})
|
||||||
|
: this.markers[marker_id];
|
||||||
}
|
}
|
||||||
private update() {
|
private update() {
|
||||||
const zoom = this.mapsService.getZoom();
|
const zoom = this.mapsService.getZoom();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-core",
|
"name": "@antv/l7-core",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"@mapbox/tiny-sdf": "^1.1.1",
|
"@mapbox/tiny-sdf": "^1.1.1",
|
||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7",
|
"name": "@antv/l7",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
|
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -24,11 +24,11 @@
|
||||||
"author": "antv",
|
"author": "antv",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-component": "^2.0.8",
|
"@antv/l7-component": "^2.0.9",
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-layers": "^2.0.8",
|
"@antv/l7-layers": "^2.0.9",
|
||||||
"@antv/l7-maps": "^2.0.8",
|
"@antv/l7-maps": "^2.0.9",
|
||||||
"@antv/l7-scene": "^2.0.8",
|
"@antv/l7-scene": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7"
|
"@babel/runtime": "^7.7.7"
|
||||||
},
|
},
|
||||||
"gitHead": "9fabb78790428d2025b89fb6146fc555cb1d987d",
|
"gitHead": "9fabb78790428d2025b89fb6146fc555cb1d987d",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-layers",
|
"name": "@antv/l7-layers",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "L7's collection of built-in layers",
|
"description": "L7's collection of built-in layers",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -22,9 +22,9 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-source": "^2.0.8",
|
"@antv/l7-source": "^2.0.9",
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"@mapbox/martini": "^0.1.0",
|
"@mapbox/martini": "^0.1.0",
|
||||||
"@turf/meta": "^6.0.2",
|
"@turf/meta": "^6.0.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-maps",
|
"name": "@antv/l7-maps",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"gl-matrix": "^3.1.0",
|
"gl-matrix": "^3.1.0",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-renderer",
|
"name": "@antv/l7-renderer",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
"gl": "^4.4.0"
|
"gl": "^4.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-scene",
|
"name": "@antv/l7-scene",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -22,11 +22,11 @@
|
||||||
"author": "xiaoiver",
|
"author": "xiaoiver",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-component": "^2.0.8",
|
"@antv/l7-component": "^2.0.9",
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-maps": "^2.0.8",
|
"@antv/l7-maps": "^2.0.9",
|
||||||
"@antv/l7-renderer": "^2.0.8",
|
"@antv/l7-renderer": "^2.0.9",
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
"mapbox-gl": "^1.2.1",
|
"mapbox-gl": "^1.2.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-source",
|
"name": "@antv/l7-source",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
"author": "lzxue",
|
"author": "lzxue",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/l7-core": "^2.0.8",
|
"@antv/l7-core": "^2.0.9",
|
||||||
"@antv/l7-utils": "^2.0.8",
|
"@antv/l7-utils": "^2.0.9",
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"@mapbox/geojson-rewind": "^0.4.0",
|
"@mapbox/geojson-rewind": "^0.4.0",
|
||||||
"@turf/helpers": "^6.1.4",
|
"@turf/helpers": "^6.1.4",
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* 生成四边形热力图
|
* 生成四边形热力图
|
||||||
*/
|
*/
|
||||||
import { IParserCfg, IParserData, ISourceCFG, ITransform } from '@antv/l7-core';
|
import { IParserData, ITransform } from '@antv/l7-core';
|
||||||
import { aProjectFlat, metersToLngLat } from '@antv/l7-utils';
|
import { Satistics } from '@antv/l7-utils';
|
||||||
import { statMap } from './statistics';
|
|
||||||
|
|
||||||
interface IGridHash {
|
interface IGridHash {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
@ -90,8 +89,8 @@ function _getGridLayerDataFromGridHash(
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
} = {};
|
} = {};
|
||||||
if (option.field && option.method) {
|
if (option.field && option.method) {
|
||||||
const columns = getColumn(gridHash[key].points, option.field);
|
const columns = Satistics.getColumn(gridHash[key].points, option.field);
|
||||||
item[option.method] = statMap[option.method](columns);
|
item[option.method] = Satistics.statMap[option.method](columns);
|
||||||
}
|
}
|
||||||
Object.assign(item, {
|
Object.assign(item, {
|
||||||
_id: i + 1,
|
_id: i + 1,
|
||||||
|
@ -99,6 +98,7 @@ function _getGridLayerDataFromGridHash(
|
||||||
-180 + gridOffset.xOffset * lonIdx,
|
-180 + gridOffset.xOffset * lonIdx,
|
||||||
-90 + gridOffset.yOffset * latIdx,
|
-90 + gridOffset.yOffset * latIdx,
|
||||||
],
|
],
|
||||||
|
rawData: gridHash[key].points,
|
||||||
count: gridHash[key].count,
|
count: gridHash[key].count,
|
||||||
});
|
});
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -106,8 +106,3 @@ function _getGridLayerDataFromGridHash(
|
||||||
return accu;
|
return accu;
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
function getColumn(data: any[], columnName: string) {
|
|
||||||
return data.map((item) => {
|
|
||||||
return item[columnName] * 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { aProjectFlat, metersToLngLat } from '@antv/l7-utils';
|
import { aProjectFlat, Satistics } from '@antv/l7-utils';
|
||||||
import { hexbin } from 'd3-hexbin';
|
import { hexbin } from 'd3-hexbin';
|
||||||
const R_EARTH = 6378000;
|
const R_EARTH = 6378000;
|
||||||
import {
|
import {
|
||||||
IParseDataItem,
|
IParseDataItem,
|
||||||
IParserCfg,
|
|
||||||
IParserData,
|
IParserData,
|
||||||
ISourceCFG,
|
ISourceCFG,
|
||||||
ITransform,
|
ITransform,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { statMap } from './statistics';
|
|
||||||
interface IHexBinItem<T> extends Array<T> {
|
interface IHexBinItem<T> extends Array<T> {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -39,12 +37,13 @@ export function pointToHexbin(data: IParserData, option: ITransform) {
|
||||||
const result: IParserData = {
|
const result: IParserData = {
|
||||||
dataArray: hexbinBins.map((hex: IHexBinItem<IRawData>, index: number) => {
|
dataArray: hexbinBins.map((hex: IHexBinItem<IRawData>, index: number) => {
|
||||||
if (option.field && method) {
|
if (option.field && method) {
|
||||||
const columns = getColumn(hex, option.field);
|
const columns = Satistics.getColumn(hex, option.field);
|
||||||
hex[method] = statMap[method](columns);
|
hex[method] = Satistics.statMap[method](columns);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
[option.method]: hex[method],
|
[option.method]: hex[method],
|
||||||
count: hex.length,
|
count: hex.length,
|
||||||
|
rawData: hex,
|
||||||
coordinates: [hex.x, hex.y],
|
coordinates: [hex.x, hex.y],
|
||||||
_id: index + 1,
|
_id: index + 1,
|
||||||
};
|
};
|
||||||
|
@ -56,8 +55,3 @@ export function pointToHexbin(data: IParserData, option: ITransform) {
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
function getColumn(data: IHexBinItem<IRawData>, columnName: string) {
|
|
||||||
return data.map((item: IRawData) => {
|
|
||||||
return item[columnName] * 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@antv/l7-utils",
|
"name": "@antv/l7-utils",
|
||||||
"version": "2.0.8",
|
"version": "2.0.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
|
|
|
@ -5,4 +5,5 @@ export * from './geo';
|
||||||
export * from './lru_cache';
|
export * from './lru_cache';
|
||||||
export * from './event';
|
export * from './event';
|
||||||
export * from './color';
|
export * from './color';
|
||||||
export { DOM };
|
import * as Satistics from './statistics';
|
||||||
|
export { DOM, Satistics };
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
interface IItemData {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
function max(x: number[]) {
|
function max(x: number[]) {
|
||||||
if (x.length === 0) {
|
if (x.length === 0) {
|
||||||
throw new Error('max requires at least one data point');
|
throw new Error('max requires at least one data point');
|
||||||
|
@ -75,3 +78,12 @@ export const statMap: { [key: string]: any } = {
|
||||||
mean,
|
mean,
|
||||||
sum,
|
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);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { Marker, MarkerLayer, PolygonLayer, Scene } from '@antv/l7';
|
import { Marker, MarkerLayer, PolygonLayer, Scene } from '@antv/l7';
|
||||||
import { Mapbox, GaodeMap } from '@antv/l7-maps';
|
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
export default class ClusterMarkerLayer extends React.Component {
|
export default class ClusterMarkerLayer extends React.Component {
|
||||||
private scene: Scene;
|
private scene: Scene;
|
||||||
|
@ -34,6 +34,10 @@ export default class ClusterMarkerLayer extends React.Component {
|
||||||
const nodes = await response.json();
|
const nodes = await response.json();
|
||||||
const markerLayer = new MarkerLayer({
|
const markerLayer = new MarkerLayer({
|
||||||
cluster: true,
|
cluster: true,
|
||||||
|
clusterOption: {
|
||||||
|
field: 'mag',
|
||||||
|
method: 'sum',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
|
@ -47,7 +51,9 @@ export default class ClusterMarkerLayer extends React.Component {
|
||||||
// tslint:disable-next-line:prefer-for-of
|
// tslint:disable-next-line:prefer-for-of
|
||||||
for (let i = 0; i < nodes.features.length; i++) {
|
for (let i = 0; i < nodes.features.length; i++) {
|
||||||
const { coordinates } = nodes.features[i].geometry;
|
const { coordinates } = nodes.features[i].geometry;
|
||||||
const marker = new Marker().setLnglat({
|
const marker = new Marker({
|
||||||
|
extData: nodes.features[i].properties,
|
||||||
|
}).setLnglat({
|
||||||
lng: coordinates[0],
|
lng: coordinates[0],
|
||||||
lat: coordinates[1],
|
lat: coordinates[1],
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,10 +28,7 @@ export default class HeatMapLayerDemo extends React.Component {
|
||||||
|
|
||||||
const layer = new HeatmapLayer();
|
const layer = new HeatmapLayer();
|
||||||
layer
|
layer
|
||||||
.source({
|
.source(data)
|
||||||
type: 'FeatureCollection',
|
|
||||||
features: [],
|
|
||||||
})
|
|
||||||
.shape('heatmap')
|
.shape('heatmap')
|
||||||
.size('mag', [0, 1.0]) // weight映射通道
|
.size('mag', [0, 1.0]) // weight映射通道
|
||||||
.style({
|
.style({
|
||||||
|
@ -51,9 +48,8 @@ export default class HeatMapLayerDemo extends React.Component {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
scene.addLayer(layer);
|
scene.addLayer(layer);
|
||||||
layer.setData({
|
scene.on('loaded', () => {
|
||||||
type: 'FeatureCollection',
|
console.log('scene loaded');
|
||||||
features: data.features.slice(0, 100),
|
|
||||||
});
|
});
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue