bbl-mapbox-react
v0.0.17
Published
React Mapbox 地图组件库,支持雷达、图像、标记、轨迹等多种 GIS 实体渲染
Readme
bbl-mapbox-react
React Mapbox 地图组件库,支持雷达、图像、标记、轨迹、多边形、折线、圆形等多种 GIS 实体的数据驱动渲染。
安装
pnpm add bbl-mapbox-reactPeer Dependencies
pnpm add mapbox-gl @turf/turf @svgdotjs/svg.js lodash-es dayjs eventemitter3 hotkeys-js uid pbf @mapbox/vector-tile快速开始
import { Mapbox } from 'bbl-mapbox-react';
import 'bbl-mapbox-react/style.css';
function App() {
return (
<Mapbox
center={[116.4074, 39.9042]}
zoom={12}
style="mapbox://styles/mapbox/dark-v11"
entities={[
{
id: 'marker-1',
type: 'marker',
center: [116.4074, 39.9042],
src: '/icon.png',
width: 32,
name: '标记点',
},
]}
/>
);
}组件 Props
MapboxProps
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| center | [number, number] | [116.4074, 39.9042] | 地图中心点 [经度, 纬度] |
| zoom | number | 12 | 缩放级别 |
| pitch | number | 0 | 俯仰角度 |
| bearing | number | 0 | 方位角度 |
| style | string | 'mapbox://styles/mapbox/dark-v11' | Mapbox 地图样式 URL |
| maxBounds | [[number, number], [number, number]] | - | 地图边界限制 [[西南], [东北]] |
| mode | 'display' \| 'edit' \| 'picker' | 'display' | 地图模式 |
| entities | MapEntity[] | [] | 实体数据数组 |
| selectedIds | EntityId[] | [] | 选中的实体 ID 数组 |
| layers | LayerConfig[] | [] | 自定义底图图层配置 |
| interactive | InteractionOptions | - | 交互控制配置 |
| showCoordinates | boolean \| CoordinateDisplayConfig | true | 坐标显示控件 |
| showScale | boolean \| ScaleControlConfig | true | 比例尺控件 |
| showResetView | boolean \| ResetViewControlConfig | true | 重置视图控件 |
| showRoadHighlight | boolean \| RoadHighlightControlConfig | false | 路网高亮控件 |
| popupDefaults | PopupDefaults | - | 全局 Popup 默认配置 |
| renderPopup | (entity: MapEntity) => ReactNode | - | Popup 渲染回调 |
| editConfig | EditModeConfig | - | 编辑模式配置 |
| pickerConfig | PickerModeConfig | - | 选址模式配置 |
| onMapLoad | (map: MapboxMap) => void | - | 地图加载完成回调 |
| onEntityClick | (entity: MapEntity) => void | - | 实体点击回调 |
| onPick | (result: PickerResult) => void | - | 选址回调 |
| onPopupOpen | (entityId: EntityId) => void | - | Popup 打开回调 |
| onPopupClose | (entityId: EntityId) => void | - | Popup 关闭回调 |
| className | string | - | 自定义类名 |
| containerStyle | CSSProperties | - | 容器样式 |
实体类型
所有实体均继承自 BaseEntity,包含以下公共字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string \| number | 唯一标识 |
| type | string | 实体类型 |
| name | string? | 显示名称 |
| confidence | number? | 置信度 0-1,影响透明度 |
| popup | PopupConfig? | Popup 配置 |
| center | [number, number]? | 中心点坐标 |
| customData | T? | 自定义附加数据 |
Radar - 雷达
{
type: 'radar',
center: [116.4074, 39.9042],
radius: 5000, // 半径(米)
sectorAngle: 60, // 扇形角度
isAnimating: true, // 是否播放扫描动画
rotationSpeed: 1, // 旋转速度(度/帧)
colorScheme: 'green', // 'blue' | 'green' | 'red' | 'purple' | 'cyan' | 'orange'
opacity: 70, // 透明度 0-100
showRings: true, // 显示距离环
showCenter: true, // 显示中心点
showScanLine: true, // 显示扫描线
}Image - 图片
{
type: 'image',
center: [116.4074, 39.9042],
width: 1000, // 宽度(米),高度按比例计算
src: '/map.png', // 图片 URL
rotation: 0, // 旋转角度
}Marker - 标记
{
type: 'marker',
center: [116.4074, 39.9042],
src: '/icon.png', // 图标 URL
width: 32, // 宽度(像素)
rotation: 0, // 旋转角度
anchor: 'center', // 锚点位置
}Unit - 单位(含轨迹预测)
{
type: 'unit',
center: [116.4074, 39.9042],
src: '/unit.png',
width: 40,
predicted_traj: [ // 预测轨迹
{ lon: 116.41, lat: 39.91, alt: 0 },
{ lon: 116.42, lat: 39.92, alt: 0 },
],
showTrajectory: 'all', // 轨迹显示数量:number | 'all'
showTrajectoryPoints: false, // 是否显示轨迹点
}Polygon - 多边形
{
type: 'polygon',
coordinates: [
[116.40, 39.90],
[116.41, 39.91],
[116.42, 39.90],
],
strokeColor: '#3388ff',
strokeWidth: 2,
fillColor: '#3388ff',
fillOpacity: 0.2,
}Polyline - 折线
{
type: 'polyline',
coordinates: [
[116.40, 39.90],
[116.41, 39.91],
[116.42, 39.90],
],
strokeColor: '#3388ff',
strokeWidth: 2,
lineCap: 'round',
lineJoin: 'round',
dashArray: [4, 4], // 虚线模式
}Circle - 圆形
{
type: 'circle',
center: [116.4074, 39.9042],
radius: 1000, // 半径(米)
strokeColor: '#3388ff',
fillColor: '#3388ff',
fillOpacity: 0.2,
fillType: 'solid', // 'solid' | 'radial-gradient'
showCenterPoint: true,
gradientAnimation: 'flicker', // 'static' | 'flicker' | 'breath' | 'pulse'
isAnimating: false,
}Square - 正方形
{
type: 'square',
center: [116.4074, 39.9042],
length: 1000, // 边长(米)
strokeColor: '#3388ff',
fillColor: '#3388ff',
fillOpacity: 0.2,
}Rectangle - 矩形
{
type: 'rectangle',
bounds: [[116.40, 39.90], [116.42, 39.92]], // 对角点
strokeColor: '#3388ff',
fillColor: '#3388ff',
fillOpacity: 0.2,
}Ref 方法
通过 useRef<MapboxRef> 获取组件实例,可调用以下方法:
const mapRef = useRef<MapboxRef>(null);
<Mapbox ref={mapRef} />| 方法 | 签名 | 说明 |
|------|------|------|
| getMap | () => MapboxMap \| null | 获取 Mapbox GL 地图实例 |
| flyTo | (center, zoom?, options?) => void | 飞行到指定位置 |
| flyToEntities | (ids, zoom?, options?) => void | 飞行到指定实体 |
| startAnimation | (id) => void | 启动实体动画 |
| stopAnimation | (id) => void | 停止实体动画 |
| toggleAnimation | (id) => void | 切换实体动画状态 |
| openPopup | (id) => void | 程序化打开 Popup |
| closePopup | (id) => void | 关闭指定 Popup |
| closeAllPopups | () => void | 关闭所有 Popup |
| isPopupOpen | (id) => boolean | 检查 Popup 是否打开 |
| toggleUnitTrajectory | (ids?) => void | 切换 Unit 轨迹显示 |
| getMode | () => MapMode | 获取当前模式 |
| setMode | (mode) => void | 设置地图模式 |
| startDrawing | (options) => void | 开始绘制 |
| getPickedLocation | () => PickerResult \| null | 获取选址坐标 |
| clearPickedLocation | () => void | 清除选址坐标 |
地图模式
Display 模式(默认)
只读查看模式,支持点击实体、Popup 展示。
Edit 模式
编辑模式,支持在地图上绘制和放置实体。
<Mapbox
mode="edit"
editConfig={{
showEditTools: true,
showRectangleTool: true,
showCircleTool: true,
showPolygonTool: true,
showSquareTool: true,
showPolylineTool: true,
markerTemplates: [
{ id: 'drone', name: '无人机', icon: '/drone.png', width: 40 },
],
onMarkerAdd: (marker) => console.log('新增 Marker', marker),
onRectangleAdd: (rect) => console.log('新增矩形', rect),
onCircleAdd: (circle) => console.log('新增圆形', circle),
onPolygonAdd: (polygon) => console.log('新增多边形', polygon),
onSquareAdd: (square) => console.log('新增正方形', square),
onPolylineAdd: (polyline) => console.log('新增折线', polyline),
onEntityDelete: (entity) => console.log('删除实体', entity),
}}
/>通过 Ref 的 startDrawing API 程序化触发绘制:
// 绘制 Marker
mapRef.current?.startDrawing({
id: 'drone',
name: '无人机',
icon: '/drone.png',
width: 60,
});
// 绘制矩形
mapRef.current?.startDrawing({ mode: 'rectangle' });
// 绘制圆形(自定义样式)
mapRef.current?.startDrawing({
mode: 'circle',
circleStyle: { fillColor: '#ff0000', fillOpacity: 0.3 },
});
// 绘制多边形
mapRef.current?.startDrawing({ mode: 'polygon' });
// 绘制折线
mapRef.current?.startDrawing({ mode: 'polyline' });绘制操作:
- 矩形/正方形/圆形:第一次点击设置起点/中心,第二次点击完成
- 多边形:逐点点击添加顶点,点击第一个点附近闭合,或右键完成
- 折线:逐点点击添加顶点,右键完成
- Esc 键取消当前绘制
- 右键 取消或完成绘制
Picker 模式
选址模式,点击地图获取坐标。
<Mapbox
mode="picker"
pickerConfig={{
showMarker: true,
markerColor: '#3388ff',
showCrosshair: true,
}}
onPick={(result) => {
console.log(`选中坐标: ${result.lng}, ${result.lat}`);
}}
/>底图图层
支持三种类型的底图图层叠加:
<Mapbox
layers={[
// 栅格瓦片
{
id: 'satellite',
type: 'raster',
url: 'https://example.com/tiles/{z}/{x}/{y}.png',
opacity: 0.8,
},
// Style JSON
{
id: 'custom-style',
type: 'style',
url: 'http://localhost:8080/styles/basic/style.json',
hasRoadNetwork: true,
},
// TileJSON
{
id: 'terrain',
type: 'tilejson',
url: 'http://localhost:8080/styles/terrain.json',
},
]}
/>Popup 配置
实体级 Popup 可通过 popup 字段配置,也可通过 renderPopup 统一渲染:
// 实体级配置
const entities = [
{
id: '1',
type: 'marker',
center: [116.4074, 39.9042],
src: '/icon.png',
width: 32,
popup: {
content: <div>自定义内容</div>,
trigger: 'click', // 'click' | 'hover'
position: 'top', // 'top' | 'bottom' | 'left' | 'right' | 'center'
animation: 'fade', // 'fade' | 'scale' | 'fade-scale' | 'none'
showCloseButton: true,
closeOnClickOutside: true,
closeOnEscape: true,
hoverDelay: 300,
},
},
];
// 全局渲染回调
<Mapbox
entities={entities}
renderPopup={(entity) => <div>{entity.name}</div>}
popupDefaults={{
trigger: 'click',
position: 'top',
animation: 'fade',
}}
/>交互控制
<Mapbox
interactive={{
dragPan: true,
scrollZoom: true,
doubleClickZoom: true,
touchZoomRotate: true,
keyboard: true,
dragRotate: true,
pitchWithRotate: true,
touchPitch: true,
boxZoom: true,
}}
/>导出
// 主组件
export { Mapbox } from './Mapbox';
// 类型
export type {
MapboxProps, MapboxRef, MapEntity,
RadarEntity, ImageEntity, MarkerEntity, UnitEntity,
PolygonEntity, PolylineEntity, CircleEntity, SquareEntity, RectangleEntity,
PopupConfig, PopupDefaults, LayerConfig,
InteractionOptions, MapMode, DrawMode, DrawingOptions,
MarkerTemplate, PickerResult, EditModeConfig, PickerModeConfig,
// ...更多类型
};
// 常量
export { COLOR_SCHEMES, RADAR_DEFAULTS, POPUP_DEFAULTS, ROAD_TYPE_OPTIONS };
// 子组件
export {
EntityPopup, CoordinateDisplay, ScaleControl,
ResetViewControl, RoadHighlightControl, EditControl, ContextMenu,
};
// 工具函数
export { destinationPoint, distance, bearing, mergePopupConfig, calculatePopupPosition };
// 渲染器(用于扩展)
export {
MarkerRenderer, UnitRenderer, CircleRenderer,
PolygonRenderer, PolylineRenderer, SquareRenderer, RectangleRenderer,
BaseCanvasRenderer, CanvasImageRenderer, CanvasRadarRenderer, CanvasCircleRenderer,
};开发
# 安装依赖
pnpm install
# 启动开发服务
pnpm dev
# 构建库
pnpm build:lib
# 构建项目
pnpm buildLicense
GPL-3.0
