atchain-mapbox-vue
Version:
A Vue 3 MapBox component library with subway lines, stations, markers and polygons support. Zero dependencies except Vue 3 and Mapbox GL JS.
458 lines (348 loc) • 10.6 kB
Markdown
# MapBox Vue 组件库
一个基于 Vue 3 和 Mapbox GL JS 的高性能地图组件库,支持地铁线路、站点显示、标记点和多边形等功能。
## ✨ 特性
- 🚀 **零外部依赖** - 除 Vue 3 和 Mapbox GL JS 外无其他依赖
- 📦 **模块化设计** - 可按需导入,支持 Tree Shaking
- 🎨 **样式独立** - 内置样式系统,可选择性使用 Tailwind CSS
- 🔧 **TypeScript 支持** - 完整的类型定义
- 🎯 **交互丰富** - 支持点击、悬停等交互效果
- 📱 **响应式** - 支持地图移动、缩放等响应式更新
## 📦 安装
### 方式一:NPM 安装(推荐)
```bash
npm install atchain-mapbox-vue mapbox-gl
# 或
yarn add atchain-mapbox-vue mapbox-gl
```
### 方式二:复制组件文件
将整个 `mapbox` 文件夹复制到你的项目中:
```
src/components/mapbox/
├── MapBox.vue # 主容器组件
├── MapBoxMarker.vue # 标记组件
├── MapBoxPolygon.vue # 多边形组件
├── MapBoxStations.vue # 地铁站点组件
├── MapBoxSubWay.vue # 地铁线路组件
├── useMapBox.ts # 统一入口
├── composables/ # 核心逻辑
├── styles/ # 样式系统
└── utils/ # 工具函数
```
然后安装依赖:
```bash
npm install mapbox-gl
```
## 🚀 快速开始
### 基础用法
```vue
<template>
<div class="w-full h-screen">
<MapBox
:token="mapboxToken"
:center="[121.431502, 31.214212]"
:zoom="14"
>
<!-- 在地图上添加标记点 -->
<MapBoxMarker
src="/images/marker.png"
id="marker-1"
width="50px"
height="50px"
/>
<!-- 添加多边形 -->
<MapBoxPolygon id="polygon-1" />
<!-- 添加地铁线路 -->
<MapBoxSubWay
subway-json-path="/data/subway.geojson"
:subway-render-radius-km="10"
/>
<!-- 添加地铁站点 -->
<MapBoxStations
station-json-path="/data/stations.geojson"
:show-station-names="true"
:station-render-radius-km="15"
/>
</MapBox>
</div>
</template>
<script setup lang="ts">
// NPM 安装方式
import { MapBox, MapBoxMarker, MapBoxPolygon, MapBoxSubWay, MapBoxStations } from 'atchain-mapbox-vue'
// 或复制文件方式
// import { MapBox, MapBoxMarker, MapBoxPolygon, MapBoxSubWay, MapBoxStations } from '@/components/mapbox'
const mapboxToken = 'your-mapbox-access-token'
</script>
```
## 📚 组件 API
### MapBox (主容器)
主地图容器组件,所有其他组件都需要在其内部使用。
#### Props
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `token` | `string` | - | Mapbox 访问令牌 |
| `mapStyle` | `string` | - | 地图样式 URL |
| `center` | `[number, number]` | `[121.431502, 31.214212]` | 地图中心点 |
| `zoom` | `number` | `14` | 缩放级别 |
| `jsonPath` | `string` | `'./data/landmark.geojson'` | 地标数据路径 |
| `class` | `string` | `''` | 外部 CSS 类名 |
| `customStyle` | `Record<string, string>` | `{}` | 自定义样式对象 |
| `useBuiltinStyles` | `boolean` | `true` | 是否使用内置样式 |
#### 示例
```vue
<MapBox
token="pk.eyJ1..."
map-style="mapbox://styles/mapbox/streets-v11"
:center="[116.404, 39.915]"
:zoom="12"
class="w-full h-96"
:use-builtin-styles="true"
/>
```
### MapBoxMarker (标记点)
在地图上显示自定义标记点。
#### Props
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `id` | `string` | - | 标记点 ID(对应 GeoJSON 中的 id) |
| `src` | `string` | - | 图片源路径 |
| `jsonPath` | `string` | `'./data/landmark.geojson'` | 地标数据文件路径 |
| `width` | `string` | - | 标记点宽度 |
| `height` | `string` | - | 标记点高度 |
| `class` | `string` | `''` | 外部 CSS 类名 |
| `customStyle` | `Record<string, string>` | `{}` | 自定义样式对象 |
#### 示例
```vue
<MapBoxMarker
id="landmark-1"
src="/images/poi.png"
json-path="/data/my-landmarks.geojson"
width="40px"
height="40px"
class="cursor-pointer"
/>
```
### MapBoxPolygon (多边形)
显示多边形区域。
#### Props
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `id` | `string` | - | 多边形 ID(对应 GeoJSON 中的 id) |
| `jsonPath` | `string` | `'./data/landmark.geojson'` | 地标数据文件路径 |
#### 示例
```vue
<MapBoxPolygon
id="area-1"
json-path="/data/my-areas.geojson"
/>
```
### MapBoxSubWay (地铁线路)
显示地铁线路,支持动画效果。
#### Props
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `subwayJsonPath` | `string` | `'./data/shanghai-subway.geojson'` | 地铁线路数据路径 |
| `subwayRenderRadiusKm` | `number` | `8` | 渲染半径(公里) |
#### 示例
```vue
<MapBoxSubWay
subway-json-path="/data/metro-lines.geojson"
:subway-render-radius-km="15"
/>
```
### MapBoxStations (地铁站点)
显示地铁站点。
#### Props
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `stationJsonPath` | `string` | `'./data/shanghai-subway-stations.geojson'` | 站点数据路径 |
| `showStationNames` | `boolean` | `true` | 是否显示站点名称 |
| `stationRenderRadiusKm` | `number` | `15` | 渲染半径(公里) |
#### 示例
```vue
<MapBoxStations
station-json-path="/data/metro-stations.geojson"
:show-station-names="false"
:station-render-radius-km="20"
/>
```
## 🎨 样式自定义
### 使用内置样式
组件默认使用内置样式,无需额外配置:
```vue
<MapBox :use-builtin-styles="true">
<!-- 组件内容 -->
</MapBox>
```
### 使用 Tailwind CSS
如果项目中使用 Tailwind CSS,可以直接使用 Tailwind 类名:
```vue
<MapBox class="w-full h-screen bg-gray-100">
<MapBoxMarker class="hover:scale-110 transition-transform" />
</MapBox>
```
### 自定义样式
通过 `customStyle` 属性传入自定义样式:
```vue
<MapBox
:custom-style="{
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0,0,0,0.1)'
}"
/>
```
## 📄 数据格式
### GeoJSON 格式要求
#### 地标数据 (landmark.geojson)
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "marker-1",
"properties": {
"point": "地标名称"
},
"geometry": {
"type": "Point",
"coordinates": [121.431502, 31.214212]
}
},
{
"type": "Feature",
"id": "polygon-1",
"properties": {
"polygon": "区域名称"
},
"geometry": {
"type": "Polygon",
"coordinates": [[[lng1, lat1], [lng2, lat2], ...]]
}
}
]
}
```
#### 地铁线路数据
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "1号线",
"color": "#E4002B"
},
"geometry": {
"type": "LineString",
"coordinates": [[lng1, lat1], [lng2, lat2], ...]
}
}
]
}
```
#### 地铁站点数据
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "人民广场",
"interchange": true,
"line_numbers": ["1", "2", "8"],
"color": "#E4002B"
},
"geometry": {
"type": "Point",
"coordinates": [121.431502, 31.214212]
}
}
]
}
```
## 🔧 高级用法
### 使用 Composables
如果需要更细粒度的控制,可以直接使用 composables:
```vue
<script setup lang="ts">
import { useMapBoxCore, useMapBoxData, useMapBoxLayers } from 'atchain-mapbox-vue'
const { mapInstance, mapLoaded, createMap } = useMapBoxCore()
const { loadMapData } = useMapBoxData()
const { renderSubwayLines } = useMapBoxLayers()
// 自定义地图初始化
const initMap = () => {
createMap({
token: 'your-token',
style: 'mapbox://styles/mapbox/streets-v11',
center: [121.431502, 31.214212],
zoom: 14,
container: 'custom-map'
})
}
</script>
```
### 自定义数据获取
```typescript
import { defaultDataFetcher, type DataFetcher } from 'atchain-mapbox-vue'
// 自定义数据获取函数
const customFetcher: DataFetcher = async (url, options) => {
// 自定义逻辑
const response = await fetch(url, {
headers: { 'Authorization': 'Bearer token' }
})
return response.json()
}
// 使用自定义 fetcher
await loadMapData({
url: '/api/map-data',
fetcher: customFetcher
})
```
## 🎯 交互事件
组件支持丰富的交互事件:
### 标记点交互
- **点击**: 控制台输出标记点信息
- **悬停**: 标记点放大 1.1 倍
### 多边形交互
- **点击**: 控制台输出多边形信息
- **悬停**: 高亮显示(橙色填充)
### 自定义交互
可以通过修改 `useMapBoxLayers.ts` 中的交互函数来自定义行为。
## 🚀 性能优化
### 按需渲染
地铁线路和站点支持基于地图中心点的按需渲染:
```vue
<MapBoxSubWay :subway-render-radius-km="10" />
<MapBoxStations :station-render-radius-km="15" />
```
### 数据缓存
组件内置数据缓存机制,避免重复加载。
### 图层管理
自动管理图层的创建、更新和清理,防止内存泄漏。
## 🔍 故障排除
### 常见问题
1. **地图不显示**
- 检查 Mapbox token 是否正确
- 确认容器有明确的宽高
2. **标记点不显示**
- 检查 GeoJSON 数据格式
- 确认 id 匹配
3. **样式问题**
- 检查是否正确引入 Mapbox GL CSS
- 确认 `useBuiltinStyles` 设置
### 调试模式
取消注释调试函数以获得详细日志:
```typescript
// 在 MapBoxSubWay.vue 中
const logSubwayFeatureEndpoints = (geojson: any) => {
console.log('[Debug] Feature count:', geojson.features.length)
}
```
## 📄 许可证
本组件库基于 MIT 许可证开源。
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
---
**注意**: 使用前请确保已获得有效的 Mapbox 访问令牌。