Skip to content

feat: add MarkerCluster, MultiRectangle and MultiEllipse components; fix MultiCircle props error #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions src/MarkerCluster/demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* compact: true
* transform: true
* defaultShowCode: true
*/
/**
* @desc 点聚合组件 demo
*/
import React, { useCallback, useRef } from 'react';
import { Button } from 'tdesign-react';
import { MarkerCluster, BaseMap } from 'tlbs-map-react';

/** 数据 */
const geometries = [
{
position: { lat: 39.953416, lng: 116.480945 },
},
{
position: { lat: 39.984104, lng: 116.407503 },
},
{
position: { lat: 39.908802, lng: 116.497502 },
},
{
position: { lat: 40.040417, lng: 116.373514 },
},
{
position: { lat: 39.953416, lng: 116.380945 },
},
{
position: { lat: 39.984104, lng: 116.307503 },
},
{
position: { lat: 39.908802, lng: 116.397502 },
},
{
position: { lat: 40.040417, lng: 116.273514 },
},
];

export default () => {
const markerClusterRef: any = useRef(null);

/** 打印图层实例 */
const printInstance = useCallback(() => {
console.log('🚀🚀🚀 打印图层实例', markerClusterRef.current);
}, []);

/**
* 图层点击事件处理器
* @param event
*/
const clickHandler = useCallback((event: TMap.MapEvent) => {
console.log('🚀🚀🚀 图层点击事件', event);
}, []);

return (
<div className='demo-box'>
<div className="action-box">
<Button type="button" onClick={printInstance}>
打印图层实例
</Button>
</div>
<BaseMap
apiKey="OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"
options={{
zoom: 10,
}}
>
<MarkerCluster
ref={markerClusterRef}
geometries={geometries}
onClick={clickHandler}
/>
</BaseMap>
</div>
);
};
31 changes: 31 additions & 0 deletions src/MarkerCluster/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 点聚合 MarkerCluster

**1. 组件示例**

<code src="./demo.tsx"></code>
:::info{title=提示}
点击地图下方最右侧图标 `</>` 可展开代码
:::

**2. 组件 Props**

| 属性 | 类型 | 说明 | 可选性 | 默认值 |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------- | :----- | :--------- |
| id | string | 图层 id,若没有会自动分配一个 | 可选 | |
| geometries | [PointGeometry[]](https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocMarker#6) | 点聚合数据数组 | 可选 | [] |
| **options** | [Omit<TMap.MarkerClusterOptions, 'map' &#124; 'id' &#124; 'geometries'>](https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocCluster#2) | 点聚合配置参数(官网) | 可选 | 官网默认值 |

**MarkerClusterOptions**
| 属性名称 | 类型 | 说明 |
| :--------- | :-------------------- | :------------------------------ |
| id | String | 图层 id,若没有会自动分配一个。 |
| map | Map | 显示点聚合图层的底图。 |
| zIndex | Number | 图层绘制顺序。 |
| geometries | PointGeometry[] | 点聚合数据数组。 |
| enableDefaultStyle | Boolean | 是否启用默认的聚合样式。 |
| minimumClusterSize | Number | 形成聚合簇的最小个数,默认为 2。 |
| zoomOnClick | Boolean | 点击已经聚合的标记点时是否实现聚合分离,默认为 true。 |
| gridSize | Number | 聚合算法的可聚合距离,即距离小于该值的点会聚合至一起,默认为 60,以像素为单位,指的是地图 pitch 为 0 时的屏幕像素大小。 |
| averageCenter | Boolean | 每个聚和簇的中心是否应该是聚类中所有标记的平均值,默认为 false。 |
| maxZoom | Number | 采用聚合策略的最大缩放级别,若地图缩放级别大于该值,则不进行聚合。默认为 20。 |
| collisionOptions |[CollisionOptions](https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocCluster#4) | 图层碰撞配置参数。 |
82 changes: 82 additions & 0 deletions src/MarkerCluster/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* @desc 点聚合组件
*/
import React, { useContext, useEffect, useImperativeHandle, useState } from 'react';
import { MapContext, useEventListener } from 'tlbs-map-react';
import { CustomPointGeometry } from 'tlbs-map-react/interfaces';

/**
* 生成几何信息数组
* @param geos 几何信息数组
*/
const getGeometries = (geos: CustomPointGeometry[]) => geos.map((item) => {
const { position, ...rest } = item;
return {
...rest,
position: new TMap.LatLng(item.position.lat, item.position.lng),
};
});

interface MarkerClusterProps {
/**
* 图层id,若没有会自动分配一个
*/
id?: string;
/**
* 点聚合数据数组
*/
geometries?: CustomPointGeometry[]
/**
* GL API 参数
*/
options?: Omit<TMap.MarkerClusterOptions, 'map' | 'id' | 'geometries'>;
[key: string]: any;
}

const MarkerClusterComponent: React.FC<MarkerClusterProps> = React.forwardRef((props, ref) => {
const {
id,
geometries = [],
options = {},
} = props as MarkerClusterProps;

const map = useContext(MapContext); // 获取地图实例
const [instance, setInstance] = useState<TMap.MarkerCluster>(); // 存储点聚合图层实例

/** 初始化点聚合图层 */
const initMarkerCluster = () => {
if (!map) return;

const markerClusterInstance = new TMap.MarkerCluster({
...options,
map,
id,
geometries: getGeometries(geometries),
});
setInstance(markerClusterInstance);
};

// @hook 初始化点聚合图层
useEffect(() => {
if (!instance) initMarkerCluster();

return () => {
instance?.setMap(null);
};
}, [map, instance]);

// @hook 绑定事件
useEventListener(instance, props);

// @hook 给父组件暴露实例
useImperativeHandle(ref, () => instance, [instance]);

// @hook 监听几何信息改变
useEffect(() => {
instance?.setGeometries(getGeometries(geometries));
}, [geometries]);

return null;
});

export default MarkerClusterComponent;
75 changes: 45 additions & 30 deletions src/MultiCircle/demo.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,60 @@

/**
* compact: true
* transform: true
* defaultShowCode: true
*/
/**
* @desc 圆形组件 demo
*/
import React, { useCallback, useRef, useState } from 'react';
import { MultiCircle, BaseMap } from 'tlbs-map-react';
import { Button } from 'tdesign-react';
import { MultiCircle, BaseMap } from 'tlbs-map-react';

/** 样式 */
const styles = {
circleStyle1: {
color: 'rgba(41,91,255,0.16)',
circle1: {
color: 'rgba(255, 73, 0, 0.2)',
borderColor: '#FF4900',
showBorder: true,
borderColor: 'rgba(41,91,255,1)',
borderWidth: 2,
},
circleStyle2: {
color: 'rgba(41,91,255, 0.6)',
circle2: {
color: 'rgba(255, 206, 0, 0.2)',
borderColor: '#FC0',
showBorder: true,
borderColor: 'rgba(41,91,255,1)',
borderWidth: 2,
},
};

/** 数据 */
const geometriesData1 = [{
styleId: 'circleStyle1',
center: { lat: 40.0404, lng: 116.2735 },
radius: 100,
}];
const geometriesData2 = [{
styleId: 'circleStyle2',
center: { lat: 40.0415, lng: 116.2763 },
radius: 100,
}];

const geometriesData1 = [
{
styleId: 'circle1',
center: { lat: 40.0404, lng: 116.2735 },
radius: 100,
},
];
const geometriesData2 = [
{
styleId: 'circle2',
center: { lat: 40.0415, lng: 116.2763 },
radius: 80,
},
];

export default () => {
const layerRef: any = useRef(null); // 图层实例
const circleRef: any = useRef(null);
const [geometries, setGeometries] = useState<any>(geometriesData1);

const [geometries, setGeometries] = useState(geometriesData1);
/** 打印图层实例 */
const printInstance = useCallback(() => {
console.log('🚀🚀🚀 打印图层实例', layerRef.current);
console.log('🚀🚀🚀 打印图层实例', circleRef.current);
}, []);

/**
* 图层点击事件处理器
* @param event
*/
const clickHandler = useCallback((event: TMap.MapEvent) => {
console.log('🚀🚀🚀 图层点击事件', event);
}, []);

return (
Expand All @@ -48,24 +64,23 @@ export default () => {
打印图层实例
</Button>
<Button type="button" onClick={() => setGeometries(geometriesData1)}>
腾讯北京总部大楼
腾讯北京总部大厦
</Button>
<Button type="button" onClick={() => setGeometries(geometriesData2)}>
北京新浪总部大楼
北京新浪总部大厦
</Button>
</div>
<BaseMap
apiKey="OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"
options={{
center: { lat: 40.0404, lng: 116.2735 },
zoom: 17,
baseMap: { type: 'vector', features: ['base', 'building3d'] },
}}
>
<MultiCircle
ref={layerRef}
geometries={geometries}
ref={circleRef}
styles={styles}
geometries={geometries}
onClick={clickHandler}
/>
</BaseMap>
</div>
Expand Down
Loading