gis-maplibre
GisMapLibre
基于 Vue 3 + MapLibre GL + Naive UI 的企业级 GIS 地图组件库
目录
- 简介
- 功能特性
- 技术栈
- 项目架构
- 环境要求
- 安装
- 快速开始
- Props 属性详解
- Events 事件详解
- Slots 插槽
- 组件暴露方法 (defineExpose)
- 类型定义
- 完整使用示例
- 构建产物说明
- 本地开发与调试
- npm 发布流程
- 贡献指南
- 常见问题 (FAQ)
- 更新日志
- 许可证
简介
gis-maplibre 是一个面向二次封装和业务开发者的 Vue 3 组件库,它封装了 MapLibre GL JS 的核心能力,提供:
- 开箱即用的地图面板:搜索过滤、图例、图层管理、工具栏、底图切换、测量工具等
- 声明式图层配置:用 Vue 的响应式数据驱动图层增删改查,无需直接操作 MapLibre API
- 完整 TypeScript 支持:所有 Props、Events、Exposed Methods 都有完整的类型定义
- 灵活的响应式布局:内置
n-split分割面板,支持左右/上下分割 + 自定义插槽 - 企业级过滤系统:前端 filter 表达式 + 服务端 URL 参数 / SQL 参数化查询双通道
功能特性
| 类别 | 功能 |
|---|---|
| 🗺️ 数据源 | GeoJSON、Vector Tiles、Raster、Raster-DEM、Image |
| 🎨 样式体系 | 颜色、透明度、边框、线宽、填充轮廓、栅格饱和度/对比度、文字标注样式,全部运行时可变 |
| 📐 测量工具 | 距离测量、面积测量、坐标拾取,支持拖拽编辑节点、多测量列表管理 |
| 🔍 智能过滤 | 多字段条件过滤(前端 filter + 服务端 URL/SQL)、防抖输入、图层级过滤持久化 |
| 📊 图层管理器 | 树形结构、显隐控制、样式调整、拖拽排序、飞行定位、图层删除 |
| 🎯 要素交互 | Popup 弹窗、框选/点选/Ctrl+Shift 多选 |
| ⚡ 动画特效 | 自定义闪烁图层(requestAnimationFrame)、批量要素闪烁(setFeatureState) |
| 🖼️ 灵活布局 | 左右分割(gitLeft 插槽)、上下分割(gisFooter 插槽),面板大小/显隐响应式控制 |
| 💡 图层导入 | 拖拽/上传 GeoJSON 文件,自动识别几何类型并配置默认样式 |
| 📦 TypeScript | 完整的 Props/Events/Exposed 类型定义 |
| 🌐 本地化 | 内置 Naive UI 中文语言包 |
技术栈
| 依赖 | 用途 |
|---|---|
| Vue 3.4+ | 组件框架 (Composition API + <script setup>) |
| Pinia 2.1+ | 状态管理(图层状态、搜索条件持久化) |
| MapLibre GL 4.1+ | 地图渲染引擎 |
| Naive UI 2.38+ | UI 组件库(按钮、模态框、分割面板、上传等) |
| Turf.js 6.5+ | 空间分析(缓冲区、面积计算、坐标转换) |
| dayjs | 日期处理 |
| @vicons/ionicons5 | 图标库 |
| Vite 4.5+ | 构建工具 |
| TypeScript 5.4 | 类型系统 |
环境要求
| 依赖 | 版本要求 |
|---|---|
| Node.js | >= 18.0.0 |
| Vue | >= 3.4.0 |
| Pinia | >= 2.1.0(必须安装并注册) |
| 包管理器 | pnpm(推荐)/ npm / yarn |
安装
# pnpm(推荐)
pnpm install gis-maplibre
# npm
npm install gis-maplibre
# yarn
yarn add gis-maplibre
快速开始
1. 注册 Pinia(必须)
组件内部使用 Pinia 管理图层状态。必须在使用组件前注册 Pinia:
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia()) // ⚠️ 必须先注册 Pinia
app.mount('#app')
2. 注册组件
方式一:全局注册
// main.ts
import GisMapLibre from 'gis-maplibre'
import 'gis-maplibre/dist/style.css'
app.use(GisMapLibre) // 全局注册后可在任何组件中使用 <GisMapLibre>
方式二:按需引入
import { GisMapLibre } from 'gis-maplibre'
import 'gis-maplibre/dist/style.css'
3. 引入样式(必须)
⚠️ 版本 >=1.0.8 后 不再自动注入样式,必须手动引入:
// main.ts 或 App.vue 的 <script setup> 中
import 'gis-maplibre/dist/style.css'
// 或者直接在 CSS 文件中
// @import 'gis-maplibre/dist/style.css';
4. 基础使用
重要:地图容器必须有明确的高度,否则地图无法渲染。
<template>
<div class="map-container">
<GisMapLibre
ref="mapRef"
:config-state="configState"
:map-config="mapConfig"
:base-layers="baseLayers"
:overlay-layers="overlayLayers"
:toolbar-data="toolbarData"
:split-config="splitConfig"
:add-control-config="addControlConfig"
@init-complete="onMapInit"
@toolbar-event="onToolbarEvent"
@layer-feature-click="onLayerClick"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
// ⚠️ 注意:当前版本不导出类型,需要用 import type 时需要自己声明类型接口
const mapRef = ref()
// 地图初始化配置(与内置默认值深度合并)
const mapConfig = {
center: [116.397, 39.908],
zoom: 10,
style: {
glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf'
}
}
// 组件状态配置
const configState = reactive({
showLayerManager: true,
addLayerIsDel: false
})
// 底图配置
const baseLayers = [
{
id: 'satellite',
name: '卫星影像',
type: 'raster',
url: 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
visible: true,
opacity: 1,
thumbColor: '#2d5016'
}
]
// 叠加图层(必须用 ref/reactive,否则动态更新不触发)
const overlayLayers = ref([])
// 工具栏
const toolbarData = [
{ key: 'translation', name: '平移', type: 'translation', isShow: true },
{ key: 'measure', name: '测距', type: 'measure', isShow: true },
{ key: 'area', name: '测面积', type: 'area', isShow: true },
{ key: 'coordinate', name: '坐标拾取', type: 'coordinate', isShow: true }
]
// 布局配置(必须用 reactive)
const splitConfig = reactive({
split1: { defaultSize: 0, disabled: true, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 },
split2: { defaultSize: 1, disabled: true, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 }
})
// 控件
const addControlConfig = [
{ key: 'NavigationControl', position: 'top-left' },
{ key: 'ScaleControl', position: 'bottom-left' },
{ key: 'SearchControl', icon: 'SearchOutline', position: 'top-right', type: 'icon' },
{ key: 'ToolbarControl', icon: 'GridOutline', position: 'top-right', type: 'icon' },
{ key: 'LayerControl', icon: 'LayersOutline', position: 'top-right', type: 'icon' }
]
const onMapInit = (map: any) => { console.log('地图就绪', map) }
const onToolbarEvent = (e: any) => { console.log('工具事件', e) }
const onLayerClick = (data: any) => { console.log('图层点击', data) }
</script>
<style>
.map-container {
width: 100%;
height: 100vh;
position: relative;
}
</style>
Props 属性详解
mapConfig
- 类型:
Partial<maplibregl.MapOptions> - 默认值:与内置默认值深度合并
MapLibre GL 地图初始化配置,会与以下内置默认值合并:
const defaultMapConfig = {
container: mapId, // 自动生成唯一容器 ID
style: { version: 8, sources: {}, layers: [] },
center: [109.134065, 39.506786], // 默认中心(中国中部)
zoom: 4,
attributionControl: false // 不显示 MapLibre 版权控件
}
常用覆盖项:center、zoom、style.glyphs(字体路径)。
configState
- 类型:
ConfigState - 默认值:见下方
组件状态配置对象,控制面板显隐、公共过滤、图层删除行为。
interface ConfigState {
showToolbar?: boolean // 工具栏初始是否显示(默认 false)
showLegend?: boolean // 图例初始是否显示(默认 false)
showLayerManager?: boolean // 图层管理器初始是否显示(默认 false)
showSearchManager?: boolean // 搜索管理器初始是否显示(默认 false)
addLayerIsDel?: boolean // overlayLayers 变化时是否先删除旧图层再重新添加(默认 false)
publicFilter?: PublicFilterItem[] // 全局公共过滤条件,应用于所有图层
}
publicFilter 单项结构
interface PublicFilterItem {
field: string // 过滤属性字段名
comparator: string // 比较运算符
value: any // 过滤值
isParameter?: boolean // 是否为服务端参数过滤(默认 false)
parameterType?: 'params' | 'sql' // 参数类型:'params'=拼接到 URL、'sql'=生成 SQL WHERE 子句
defaultFilter?: boolean // 是否作为默认过滤条件(默认 false)
}
使用示例:
const configState = reactive({
publicFilter: [
{
field: 'keyName',
comparator: '==',
value: '值',
isParameter: true,
parameterType: 'params'
}
]
})
baseLayers
- 类型:
BaseLayersConfig[] - 默认值:
[]
底图图层配置数组,用于底图切换(在底图面板中显示为可选项)。
interface BaseLayersConfig {
id: string // 唯一标识(必填)
name: string // 显示名称
type: string // 底图类型,通常为 'raster'
url: string // 瓦片地址模板,支持 {x}/{y}/{z} 占位符
visible: boolean // 是否默认可见
opacity: number // 透明度 0-1
thumbColor: string // 底图切换面板中的缩略图颜色
}
示例:
const baseLayers = [
{
id: 'satellite',
name: '卫星影像',
type: 'raster',
url: 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
visible: true,
opacity: 1,
thumbColor: '#2c3e50'
},
{
id: 'streets',
name: '街道地图',
type: 'raster',
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
visible: false,
opacity: 1,
thumbColor: '#f39c12'
}
]
overlayLayers
- 类型:
LayerConfig[] - 默认值:
[]
叠加图层配置数组,这是核心配置。必须使用 ref() 或 reactive() 包装,否则动态增删图层不会响应。
LayerConfig 完整结构
interface LayerConfig {
// ===== 基本信息 =====
id: string // 图层唯一标识(必填,不可重复)
name: string // 图层显示名称
type: 'geojson' | 'vector' | 'raster' | 'raster-dem' | 'image' // 数据源类型(必填)
// ===== 数据源(按 type 选择) =====
data?: GeoJSON.GeoJSON // type='geojson' 时的数据(GeoJSON 对象)
url?: string // type='vector'/'raster'/'raster-dem' 时的数据源 URL/tilejson
tiles?: string[] // type='vector'/'raster' 时的瓦片地址数组(优先于 url)
imageUrl?: string // type='image' 时的图片 URL
imageCoordinates?: [ // type='image' 时的图片四角坐标 [左上, 右上, 右下, 左下]
[number, number],
[number, number],
[number, number],
[number, number]
]
// ===== 图源/样式配置(可选,遵循 MapLibre 规范)=====
source?: object // 自定义 MapLibre Source 配置
sourceLayer?: string // Vector 瓦片的 source-layer 名称
layers?: object | object[] // 自定义图层样式,遵循 MapLibre Layer 规范
// ===== 显示与交互 =====
visible: boolean // 是否可见
isClick?: boolean // 是否响应点击(触发 layer-feature-click 事件)
autoFly?: boolean // 加载后是否自动飞行到图层范围(默认 false)
deletable?: boolean // 是否允许用户在图层管理器中删除(默认 true)
// ===== 样式相关 =====
shape?: 'circle' | 'square' | 'triangle' | 'diamond' | 'line' | 'polygon' | 'raster'
// 图层形状,用于图例显示和样式分支
sourceType?: 'point' | 'line' | 'polygon' | 'raster'
// 数据源空间类型,优先级高于 shape
// ===== 层级 =====
zIndex?: number // 渲染层级,数值越大越靠上
children?: LayerConfig[] // 子图层列表(树形结构)
// ===== 过滤 =====
defaultFilter?: FilterItem[] // 初始过滤条件
filterFields?: FilterFieldConfig[] // 搜索面板的过滤字段配置
// ===== 图标 =====
icon?: string // 自定义图标路径/URL
iconName?: string // 图标名称(添加到 MapLibre image sprite)
iconColor?: string // 图标颜色
// ===== 高亮 =====
highlight?: HighlightConfig // hover 高亮配置
// ===== 内部标记 =====
isImported?: boolean // 是否为导入图层(通常不需手动设置)
}
FilterItem 结构
interface FilterItem {
field: string // 属性字段名
comparator: string // 比较运算符(同 publicFilter)
value: any // 过滤值
isDisabledDelete?: boolean // 是否禁止用户删除该过滤条件(默认 false)
isParameter?: boolean // 是否为服务端参数过滤(默认 false)
parameterType?: 'params' | 'sql' // 参数类型
isLayerAttr?: boolean // 是否为图层属性过滤(默认 false)
}
FilterFieldConfig 结构
interface FilterFieldConfig {
label: string // 显示标签
value: string // 数据中的属性字段名
type: 'input' | 'select' | 'number' | 'date' // 表单控件类型
dateType?: DatePickerType // type='date' 时的 NDatePicker 类型
transformation?: TransformFn // 过滤转换函数(拼接条件前执行)
valueAssignmentTransFormation?: TransformFn // 赋值转换函数(回填前执行)
options?: any[] // type='select' 时的下拉选项
isParameter?: boolean // 是否为服务端参数(URL/SQL)
parameterType?: 'params' | 'sql' // 参数类型
isLayerAttr?: boolean // 是否为图层属性过滤(默认 false)
isDisabledDelete?: boolean // 是否禁止用户删除该字段(默认 false)
time?: number // 输入防抖延迟(ms),仅 isLayerAttr=true 时生效
}
dataConfig.ts 中的内置控件列表(供参考):
| key | 控件名称 | 来源 | 用途 |
|---|---|---|---|
NavigationControl |
导航控件 | MapLibre 原生 | 缩放、旋转 |
FullscreenControl |
全屏控件 | MapLibre 原生 | 全屏切换 |
ScaleControl |
比例尺 | MapLibre 原生 | 比例尺显示 |
TerrainControl |
地形控件 | MapLibre 原生 | 地形开关 |
SearchControl |
搜索 | 系统控件 | 搜索/过滤面板 |
ToolbarControl |
工具 | 系统控件 | 工具栏 |
LayerControl |
图层 | 系统控件 | 图层管理器 |
LegendControl |
图例 | 系统控件 | 图例面板 |
MapControl |
地图 | 系统控件 | 底图切换 |
CoordinatePickControl |
坐标拾取 | 系统控件 | 拾取坐标 |
TranslationControl |
平移 | 系统控件 | 平移模式 |
ImportControl |
导入 | 系统控件 | GeoJSON 导入 |
AreaControl |
测面 | 系统控件 | 面积测量(含子菜单) |
RangControl |
测距 | 系统控件 | 距离测量(含子菜单) |
selectElements |
选择 | 系统控件 | 要素选择(含子菜单) |
关键行为说明:
| key | 行为 |
|---|---|
| SearchControl | 打开/关闭搜索过滤面板 |
| ToolbarControl | 打开/关闭工具栏 |
| LayerControl | 打开/关闭图层管理器 |
| LegendControl | 打开/关闭图例面板 |
| MapControl | 打开/关闭底图切换面板 |
| CoordinatePickControl | 进入坐标拾取模式,点击地图获取坐标并复制到剪贴板 |
| AreaControl | 带子菜单:开始测量 / 删除 |
| RangControl | 带子菜单:开始测量 / 删除 |
| selectElements | 带子菜单:开始选择 / 清空选择 |
Events 事件详解
| 事件名 | 参数签名 | 触发时机 |
|---|---|---|
init-complete |
(map: maplibregl.Map) |
地图初始化完成(load 事件后) |
toolbar-event |
(event: ToolbarEvent) |
工具栏按钮点击、测量完成、坐标拾取、要素选择变更等 |
map-event |
(event: { type, data }) |
统一定义的地图事件(图层导入/删除等) |
layer-feature-click |
(dataInfo: Record<string, { feature, properties, event }>) |
isClick: true 的图层被点击(300ms 防抖) |
control-click |
(event: { key: string }) |
自定义控件按钮被点击 |
layer-delete |
(layerId: string) |
图层被删除 |
overlay-layers-reorder |
(layers: LayerConfig[]) |
叠加图层顺序被重排 |
deleted-event |
(event: any) |
测量结果被删除 |
dragged-event |
(event: any) |
测量节点被拖拽 |
search-layer-filter-data |
(layerId: string, filterData: any) |
搜索组件的过滤条件变化 |
toolbar-event 详情
toolbar-event 的 event 对象结构取决于操作类型:
// 普通按钮点击
{ key: 'myCustomButton', name: '自定义按钮', type: 'button', action: 'click' }
// 测距完成
{
key: 'measure', name: '测距', type: 'measure',
data: {
id: string, type: 'distance',
distance: number, unit: string, // unit 如 'km'、'm'
points: number[][], coordinates: number[][]
}
}
// 测面积完成
{
key: 'area', name: '测面积', type: 'area',
data: {
id: string, type: 'area',
area: number, unit: string, // unit 如 'km²'、'm²'
points: number[][], coordinates: number[][]
}
}
// 坐标拾取
{
key: 'coordinate', name: '坐标拾取', type: 'coordinate',
action: 'end',
data: { lng: number, lat: number }
}
// 要素选择(实时推送选中结果)
{
key: 'selectElements', name: '选择要素', type: 'selectElements',
action: 'update',
value: Record<string, any[]> // { [layerId]: [feature1, feature2, ...] }
}
Slots 插槽
| 插槽名 | 位置 | 显示条件 | 说明 |
|---|---|---|---|
gitLeft |
左侧面板 | split1.disabled === false |
常用于放自定义面板或统计图表 |
gisHeader |
地图上方 | 始终渲染 | 可用于自定义工具栏、标题栏等 |
gisFooter |
底部面板 | split2.disabled === false |
常用于结果面板、分析弹窗等 |
Props 属性详解(续)
toolbarData
- 类型:
ToolbarButtonConfig[] - 默认值:
[]
工具栏按钮配置数组,定义地图上方工具栏显示的按钮。
interface ToolbarButtonConfig {
key: string // 唯一标识(内置类型见下表)
name: string // 按钮显示名称
type?: string // 按钮类型:内置工具类型名 | 'button' | 'select'
isShow?: boolean // 是否显示在工具栏上
icon?: string // Naive UI 图标名,如 'BarChartOutline'
iconSize?: number // 图标大小
options?: Array<{ // type='select' 时的下拉选项
label: string
value: string
icon?: string
}>
}
内置工具栏 key 及其行为:
| key | name | 行为 |
|---|---|---|
translation |
平移 | 退出所有测量/选择模式,恢复地图拖拽 |
measure |
测距 | 进入距离测量模式 |
area |
测面积 | 进入面积测量模式 |
coordinate |
坐标拾取 | 点击地图获取坐标并复制到剪贴板 |
layerManager |
图层管理 | 打开图层管理器面板 |
legend |
图例 | 打开图例面板 |
importLayer |
导入图层 | 打开 GeoJSON 导入弹窗 |
selectElements |
选择要素 | 进入要素选择模式 |
自定义按钮示例:
const toolbarData = [
{ key: 'translation', name: '平移', type: 'translation', isShow: true },
// 自定义普通按钮(通过 toolbar-event 监听点击)
{ key: 'statisticalAnalysis', name: '统计分析', type: 'button', isShow: true, icon: 'BarChartOutline' },
// 自定义下拉按钮
{
key: 'yearSelect', name: '年度', type: 'select', isShow: true,
options: [
{ label: '2024年', value: '2024' },
{ label: '2025年', value: '2025' }
]
}
]
splitConfig
- 类型:
SplitConfig - 默认值:见下方
布局分割配置,控制左侧面板和底部面板的显隐与大小。必须使用 reactive() 包装。
interface SplitConfig {
split1: { // 左右分割(左侧面板 = gitLeft 插槽)
defaultSize: number | string // 默认大小(0-1 为比例,'200px' 为固定像素)
disabled: boolean // true=隐藏面板,false=显示
size?: number | string // 受控大小(通常用 defaultSize 即可)
watchProps: string[] // Naive UI n-split 监听属性,固定 ['defaultSize']
min: number // 最小值(0-1 比例)
max: number // 最大值(0-1 比例)
}
split2: { // 上下分割(底部面板 = gisFooter 插槽)
defaultSize: number | string
disabled: boolean
size?: number | string
watchProps: string[]
min: number
max: number
}
}
动态控制示例:
const splitConfig = reactive({
split1: { defaultSize: 0, disabled: true, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 },
split2: { defaultSize: 1, disabled: true, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 }
})
// 打开左侧面板
function openLeftPanel() {
splitConfig.split1.defaultSize = 0.3
splitConfig.split1.disabled = false
}
// 打开底部面板(40% 高度)
function openFooterPanel() {
splitConfig.split2.defaultSize = 0.4
splitConfig.split2.disabled = false
}
// 关闭所有面板
function closeAll() {
splitConfig.split1.disabled = true
splitConfig.split2.disabled = true
}
addControlConfig
- 类型:
ControlConfig[] | null - 默认值:
null
自定义地图控件配置。传 null 时使用内置默认控件组(见 dataConfig.ts)。
interface ControlConfig {
key: string // 控件标识(见控件一览表)
icon?: string // Naive UI 图标名(icon 类型控件)
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
type?: string // 控件类型:'icon' 等
title?: string // 控件提示文字
size?: number // 图标大小
callBack?: (event: any) => void // 自定义点击回调(可选)
children?: ControlConfig[] // 子控件(嵌套菜单)
}
示例:
const addControlConfig = [
// MapLibre 原生控件
{ key: 'NavigationControl', position: 'top-left' },
{ key: 'FullscreenControl', position: 'top-left' },
{ key: 'ScaleControl', position: 'bottom-left' },
// 系统控件
{ key: 'SearchControl', icon: 'SearchOutline', position: 'top-right', type: 'icon' },
{ key: 'LayerControl', icon: 'LayersOutline', position: 'top-right', type: 'icon' },
// 带子菜单的自定义控件
{
key: 'customGroup',
icon: 'GridOutline',
position: 'top-right',
type: 'icon',
title: '自定义工具组',
children: [
{ key: 'customAction1', icon: 'PlayOutline', type: 'icon', title: '动作一' },
{ key: 'customAction2', icon: 'TrashOutline', type: 'icon', title: '动作二' }
]
}
]
组件暴露方法 (defineExpose)
通过 ref 获取组件实例后,可调用以下方法和访问以下属性。
const mapRef = ref()
// 然后通过 mapRef.value.xxx 调用
核心实例(只读属性)
| 属性 | 类型 | 说明 |
|---|---|---|
map |
maplibregl.Map |
MapLibre GL 地图实例 |
maplibregl |
typeof maplibregl |
MapLibre GL 命名空间(用于创建 Popup、Marker 等) |
turf |
typeof turf |
Turf.js 空间分析工具库 |
importedLayers |
Ref<LayerConfig[]> |
导入的图层列表(响应式) |
unifiedLayers |
Ref<LayerConfig[]> |
统一图层列表(叠加图层 + 导入图层合并,响应式) |
measureMode |
Ref<'distance' | 'area' | 'coordinate' | null> |
当前测量模式 |
measureResult |
Ref<any> |
当前测量结果 |
图层管理方法
toggleLayerManager()
- 说明:切换图层管理器面板的显示/隐藏
- 参数:无
- 返回值:
void
toggleLayer(layerId: string, visible: boolean)
- 说明:切换单个图层(含其子图层)的可见性
- 参数:
layerId— 图层 IDvisible—true显示,false隐藏
- 返回值:
void
setLayersVisible(layerIds: string | string[])
- 说明:设置指定图层的可见性(勾选状态),同步更新图层管理器面板
- 参数:
layerIds— 单个图层 ID 或 ID 数组
- 返回值:
void
allLayersVisibility(layerState: boolean)
- 说明:批量控制所有图层的勾选状态
- 参数:
layerState—true全选,false取消全部
- 返回值:
void
layerChecked(checkedKeys: string[])
- 说明:批量设置图层勾选状态,未在数组中的图层取消勾选
- 参数:
checkedKeys— 需要勾选的图层 ID 数组
- 返回值:
void
layerStyleChange(layerId: string, style: LayerStyle)
- 说明:动态修改图层样式,自动路由到正确的 paint/layout 属性
interface LayerStyle {
color?: string | string[] // 填充/线条颜色
borderColor?: string | string[] // 边框颜色(面图层的 outline)
borderOpacity?: number | number[] // 边框透明度
borderWidth?: number // 边框宽度
fillOutlineColor?: string | string[] // 填充描边颜色
layerOpacity?: number | number[] // 图层整体透明度
rasterSaturation?: number // 栅格饱和度(仅 raster)
rasterContrast?: number // 栅格对比度(仅 raster)
titleColor?: string | string[] // 文字标注颜色(symbol 图层)
titleSize?: number // 文字标注大小(symbol 图层)
}
- 参数:
layerId— 图层 IDstyle— 样式配置对象
- 返回值:
void
layerDelete(layerId: string)
- 说明:从地图和图层列表中删除指定图层,同时移除关联的 source、outline、symbol 图层
- 参数:
layerId— 要删除的图层 ID
- 返回值:
void
layerReorder(layers: LayerConfig[], layerType: 'overlay' | 'imported', checkedKeys?: string[])
- 说明:对指定类型的图层进行重排
- 参数:
layers— 重排后的图层数组layerType—'overlay'(叠加图层)或'imported'(导入图层)checkedKeys— 可选,保持勾选状态的图层 ID 数组
- 返回值:
void
layerLocate(layer: LayerConfig)
- 说明:飞行定位到指定图层的空间范围。对不同类型图层采用不同策略:
- GeoJSON:直接使用数据坐标计算边界
- Vector:回到初始视口,等 idle 后查询可见要素并飞到要素范围
- Raster/Raster-DEM:回到初始视口
- Image:使用
imageCoordinates计算边界
- 参数:
layer— 图层配置对象
- 返回值:
void
UnifiedLayersReorder(unifiedLayersList: LayerConfig[], checkedKeys?: string[])
- 说明:统一图层重排(叠加图层和导入图层的统一排序),重新计算所有图层 zIndex 并移动到正确位置
- 参数:
unifiedLayersList— 重排后的统一图层列表checkedKeys— 保持勾选的图层 ID 数组
- 返回值:
void
过滤与搜索方法
searchLayerFilter(layerId: string, filter: any, urlParams: any, layer?: object, config?: object)
- 说明:对指定图层应用过滤条件,自动判断数据源类型:
- GeoJSON 源:直接设置 filter 表达式
- Vector 源:如果有 URL 参数或 SQL,重建 source 和 layer;否则直接设置 filter
- Raster/Raster-DEM/Image:不支持过滤,弹出警告
- 参数:
layerId— 目标图层 IDfilter— MapLibre filter 表达式,如['==', ['get', 'year'], '2024']urlParams— URL 参数对象,结构为{ params: string, sql: string }layer— 可选,图层配置对象config— 可选,额外配置:config.layerManagerSearch— 是否在图层管理器中标记当前选中图层config.layerSearch— 是否回填图层管理器的搜索表单
- 返回值:
void
layersFilterSet(layers: Array<{layerId: string, filters: any}>)
- 说明:批量设置多个图层的过滤条件
- 参数:
layers— 图层过滤配置数组,每项包含layerId和对应的过滤条件
- 返回值:
void
setLayerConditionsStore(layerId: string, customConditions: any)
- 说明:持久化存储图层的过滤条件(用于搜索面板状态保持)
- 参数:
layerId— 图层 IDcustomConditions— 自定义过滤条件数据
- 返回值:
void
getLayerConditionsStore(layerId: string)
- 说明:获取已存储的图层过滤条件
- 参数:
layerId— 图层 ID
- 返回值:
any— 该图层的过滤条件数据
searchMapliberParameter(filterData: FilterItem[])
- 说明:将过滤条件数组转换为 MapLibre GL filter 表达式(前端过滤用)
- 参数:
filterData— 过滤条件数组
- 返回值:
any[]— MapLibre filter 表达式数组
searchUrlParamsOrSql(filterData: FilterItem[])
- 说明:将参数化过滤条件按
parameterType拆分为 URL 参数和 SQL WHERE 子句 - 参数:
filterData— 过滤条件数组(isParameter: true的项)
- 返回值:
{ params: string, sql: string }
动画与特效方法
flyToLayer(data: GeoJSON.FeatureCollection | GeoJSON.Feature, fitBoundsOptions?: object)
- 说明:计算 GeoJSON 数据的边界并飞行定位
- 参数:
data— GeoJSON 数据fitBoundsOptions— 可选,fitBounds 配置(padding、maxZoom、duration 等)
- 默认值:padding=50, maxZoom=20, duration=1000ms
- 返回值:
void
createCustomBlinkLayer(sourceId: string, config: CustomBlinkLayerType)
- 说明:创建一个独立的闪烁图层(使用 requestAnimationFrame),常用于临时高亮
- 参数:
sourceId— 自定义数据源/图层 IDconfig— 闪烁图层配置
interface CustomBlinkLayerType {
source: { // 同 MapLibre source 规范
type: string
data?: { type: string, features: any[] }
[key: string]: any
}
layer: { // 同 MapLibre layer 规范
type: string // 图层类型:circle、line、fill 等
layout?: any
paint?: any
}
blink: {
layerKey: 'paint' | 'layout' // 要改变的属性类型
key: string // 属性 key,如 'circle-opacity'、'line-width'
frequency?: number // 闪烁频率(Hz),默认 1
minValue: number | string // 属性最小值
maxValue: number | string // 属性最大值
often?: number // 持续时长(毫秒),到期后自动停止并移除图层
}
}
- 返回值:
{ stop: () => void }— 控制对象,调用stop()停止动画并移除图层
示例:
const blinkCtrl = mapRef.value.createCustomBlinkLayer('temp-blink', {
source: { type: 'geojson', data: featureCollection },
layer: { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#ff0000' } },
blink: {
layerKey: 'paint',
key: 'circle-opacity',
frequency: 2, // 每秒闪烁 2 次
minValue: 0.2,
maxValue: 1,
often: 5000 // 5 秒后自动停止并移除
}
})
// 手动停止:blinkCtrl.stop()
startBatchBlink(targets: BlinkTarget[], options?: BlinkOptions, features?: any)
- 说明:对多个图层的指定要素进行批量闪烁(使用
setFeatureState修改isFlashing状态) - 注意:闪烁依赖图层的
promoteId配置或setFeatureState的 source/id/sourceLayer 三元组
interface BlinkTarget {
layerId: string // 图层 ID
featureIds: (string | number)[] // 要素 ID 数组
attrKey: string // 用于匹配要素的属性 key
}
interface BlinkOptions {
duration?: number // 单次闪烁时长(毫秒),默认 500
blinkTimes?: number // 闪烁次数,Infinity=无限闪烁,默认 Infinity
flyTo?: boolean // 是否自动飞行到要素范围,默认 true
visibleRange?: number // 可视范围边距(像素),要素在视口内时不飞行,超出才飞行
}
- 参数:
targets— 批量闪烁目标数组options— 闪烁选项features— 可选,预传入的要素数据(避免从地图查询)
- 返回值:
void
getFeatureGeometryById(layerId: string, key: string, featureId: any)
- 说明:从图层中查找指定 ID 的要素几何对象
- 查找策略依次为:
- GeoJSON 源的
getData() querySourceFeatures(支持多 sourceLayer)queryRenderedFeatures(当前视口内)
- GeoJSON 源的
- 参数:
layerId— 图层 IDkey— 用于匹配要素的 property keyfeatureId— 要查找的要素 ID 值
- 返回值:
Feature | null
stopBatchBlink()
- 说明:停止所有批量闪烁动画,清除所有要素的
isFlashing状态 - 参数:无
- 返回值:
void
控件方法
addControl(controlData: ControlConfig[])
- 说明:动态添加自定义控件到地图
- 参数:
controlData— 控件配置数组(同addControlConfigprop 格式)
- 返回值:
void
// 动态添加控件示例
mapRef.value.addControl([
{
key: 'myDynamicBtn',
icon: 'StarOutline',
position: 'top-right',
type: 'icon',
title: '动态按钮',
callBack: (event: any) => {
console.log('动态按钮被点击', event)
}
}
])
类型定义
LayerConfig 完整类型
详见 overlayLayers 章节的 LayerConfig 完整结构。
FilterFieldConfig 完整类型
type DatePickerType =
| 'date' | 'month' | 'year' | 'daterange' | 'monthrange' | 'yearrange'
type TransformFn = (key: string, value: any) => any
interface FilterFieldConfig {
label: string
value: string
type: 'input' | 'select' | 'number' | 'date'
dateType?: DatePickerType // type='date' 时生效
transformation?: TransformFn // 过滤值转换(拼接前)
valueAssignmentTransFormation?: TransformFn // 赋值转换(回填前)
options?: any[] // type='select' 的下拉选项
isParameter?: boolean // 是否走服务端过滤
parameterType?: 'params' | 'sql' // 参数类型
isLayerAttr?: boolean // 是否为图层属性过滤
isDisabledDelete?: boolean // 是否禁止用户删除该字段
time?: number // 防抖延迟 (ms)
}
BaseLayersConfig 完整类型
interface BaseLayersConfig {
id: string
name: string
type: string
url: string
visible: boolean
opacity: number
thumbColor: string
}
SplitConfig 完整类型
interface SplitConfig {
split1: {
defaultSize: number | string
disabled: boolean
size?: number | string
watchProps: string[]
min: number
max: number
}
split2: {
defaultSize: number | string
disabled: boolean
size?: number | string
watchProps: string[]
min: number
max: number
}
}
事件类型
type MapEventType =
| 'toolbar-click' // 工具栏按钮点击
| 'measure-complete' // 测量绘制完成
| 'area-complete' // 面积绘制完成
| 'measure-dragged' // 测量拖动完成
| 'area-dragged' // 面积拖动完成
| 'measure-deleted' // 测量删除
| 'coordinate-pick' // 坐标拾取
| 'analysis-click' // 分析按钮点击
| 'reserve-click' // 储量按钮点击
| 'layer-imported' // 图层导入完成
| 'layer-deleted' // 图层删除
interface MapEvent {
type: MapEventType
data: MapEventData
}
// 各事件数据类型
interface ToolbarClickData { key: string; name: string; action?: string; value?: string }
interface MeasureCompleteData { id: string; type: 'distance'; distance: number; unit: string; points: number[][]; coordinates: number[][] }
interface AreaCompleteData { id: string; type: 'area'; area: number; unit: string; points: number[][]; coordinates: number[][] }
interface MeasureDraggedData { id: string; type: 'distance'; distance: number; unit: string; points: number[][]; coordinates: number[][] }
interface AreaDraggedData { id: string; type: 'area'; area: number; unit: string; points: number[][]; coordinates: number[][] }
interface MeasureDeletedData { id: string; type: 'distance' | 'area'; points: number[][] }
interface CoordinatePickData { lng: number; lat: number }
interface AnalysisClickData { timestamp: number }
interface ReserveClickData { timestamp: number }
interface LayerImportedData { layerId: string; layerName: string; fileName: string; featureCount: number; geojson: GeoJSON.FeatureCollection }
interface LayerDeletedData { layerId: string; layerName: string }
Blink 相关类型
interface CustomBlinkLayerType {
source: { type: string; data?: { type: string; features: any[] }; [key: string]: any }
layer: { type: string; layout?: any; paint?: any }
blink: {
layerKey: 'paint' | 'layout'
key: string
frequency?: number // 闪烁频率 (Hz),默认 1
minValue: number | string
maxValue: number | string
often?: number // 持续时长 (ms),到期自动停止
}
}
interface BlinkTarget {
layerId: string
featureIds: (string | number)[]
attrKey: string
}
interface BlinkOptions {
duration?: number // 单次闪烁时长 (ms),默认 500
blinkTimes?: number // 闪烁次数,Infinity=无限,默认 Infinity
flyTo?: boolean // 是否自动飞行到要素范围,默认 true
visibleRange?: number // 可视范围边距 (px)
}
HighlightConfig
interface HighlightConfig {
color?: string // 线→线颜色 / 面→边框颜色 / 点→描边颜色
width?: number // 线→线宽 / 面→边框宽 / 点→描边宽
fillColor?: string // 面→填充颜色
pointColor?: string // 点→填充颜色
opacity?: number // 可选透明度
}
完整使用示例
示例一:GeoJSON 点图层 + 过滤 + 点击弹窗
<template>
<div class="map-wrap">
<GisMapLibre
ref="mapRef"
:config-state="configState"
:map-config="mapConfig"
:base-layers="baseLayers"
:overlay-layers="overlayLayers"
:toolbar-data="toolbarData"
:split-config="splitConfig"
:add-control-config="controls"
@layer-feature-click="onLayerClick"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
const mapRef = ref()
const configState = reactive({
addLayerIsDel: false,
showLayerManager: true
})
const mapConfig = {
center: [116.397, 39.908],
zoom: 10
}
const baseLayers = [
{ id: 'osm', name: 'OpenStreetMap', type: 'raster',
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
visible: true, opacity: 1, thumbColor: '#f0f0f0' }
]
const overlayLayers = ref([
{
id: 'sites',
name: '站点分布',
type: 'geojson',
shape: 'circle',
visible: true,
isClick: true,
autoFly: true,
data: {
type: 'FeatureCollection',
features: [
{ type: 'Feature',
properties: { name: '站点A', year: '2024', status: 'active' },
geometry: { type: 'Point', coordinates: [116.38, 39.90] } },
{ type: 'Feature',
properties: { name: '站点B', year: '2023', status: 'inactive' },
geometry: { type: 'Point', coordinates: [116.42, 39.92] } }
]
},
layers: [
{ type: 'circle', layerType: 'circle', layout: {},
paint: {
'circle-radius': 8,
'circle-color': '#1890ff',
'circle-opacity': 0.8,
'circle-stroke-width': 2,
'circle-stroke-color': '#fff'
} }
],
filterFields: [
{ label: '年度', value: 'year', type: 'select', options: ['2024', '2023'] },
{ label: '状态', value: 'status', type: 'select', options: ['active', 'inactive'] },
{ label: '名称', value: 'name', type: 'input', isLayerAttr: true, time: 500 }
]
}
])
const toolbarData = [
{ key: 'translation', name: '平移', type: 'translation', isShow: true },
{ key: 'measure', name: '测距', type: 'measure', isShow: true }
]
const splitConfig = reactive({
split1: { defaultSize: 0, disabled: true, size: undefined, min: 0, max: 1, watchProps: ['defaultSize'] },
split2: { defaultSize: 1, disabled: true, size: undefined, min: 0, max: 1, watchProps: ['defaultSize'] }
})
const controls = [
{ key: 'NavigationControl', position: 'top-left' },
{ key: 'ScaleControl', position: 'bottom-left' },
{ key: 'SearchControl', icon: 'SearchOutline', position: 'top-right', type: 'icon' },
{ key: 'LayerControl', icon: 'LayersOutline', position: 'top-right', type: 'icon' }
]
const onLayerClick = (dataInfo: any) => {
const layerIds = Object.keys(dataInfo)
layerIds.forEach(id => {
const { properties } = dataInfo[id]
console.log(`点击了图层 ${id},属性:`, properties)
})
}
</script>
<style scoped>
.map-wrap { width: 100%; height: 100vh; }
</style>
示例二:动态增删图层
import { ref } from 'vue'
const overlayLayers = ref<any[]>([])
const mapRef = ref()
// 添加 GeoJSON 面图层
function addPolygonLayer() {
const layerId = `polygon-${Date.now()}`
overlayLayers.value.push({
id: layerId,
name: '新多边形图层',
type: 'geojson',
shape: 'polygon',
visible: true,
isClick: true,
deletable: true,
autoFly: true,
data: {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [[
[116.25, 40.05], [116.55, 40.05],
[116.55, 39.75], [116.25, 39.75],
[116.25, 40.05]
]]
}
}]
},
layers: [
{ type: 'fill', layerType: 'fill', layout: {},
paint: { 'fill-color': '#52c41a', 'fill-opacity': 0.6, 'fill-outline-color': '#52c41a' } },
{ type: 'line', layerType: 'outline', layout: {},
paint: { 'line-color': '#237804', 'line-width': 2, 'line-opacity': 1 } }
]
})
}
// 通过 ref 调用方法删除图层
function removeLayerById(id: string) {
mapRef.value?.layerDelete(id)
}
// 修改图层样式
function changeLayerColor(layerId: string, color: string) {
mapRef.value?.layerStyleChange(layerId, {
color,
layerOpacity: 0.7
})
}
// 定位到图层
function locateToLayer(layer: any) {
mapRef.value?.layerLocate(layer)
}
// 切换图层可见性
function toggleById(layerId: string) {
mapRef.value?.toggleLayer(layerId, false)
}
示例三:矢量瓦片图层 + 服务端过滤
const overlayLayers = ref([
{
id: 'vector-buildings',
name: '建筑矢量瓦片',
type: 'vector',
shape: 'polygon',
visible: true,
tiles: ['https://api.example.com/tiles/{z}/{x}/{y}.pbf'],
sourceLayer: 'buildings',
layers: [
{ type: 'fill', layerType: 'fill', layout: {},
paint: { 'fill-color': '#ff7a45', 'fill-opacity': 0.7 } },
{ type: 'line', layerType: 'outline', layout: {},
paint: { 'line-color': '#d4380d', 'line-width': 1 } }
],
// 过滤字段配置:服务端 SQL 过滤
filterFields: [
{
label: '建筑年份',
value: 'build_year',
type: 'select',
options: [
{ label: '2020年', value: '2020' },
{ label: '2021年', value: '2021' }
],
isParameter: true, // 走服务端过滤
parameterType: 'sql' // 生成 SQL WHERE 条件
},
{
label: '建筑名称',
value: 'name',
type: 'input',
isParameter: true,
parameterType: 'params' // 拼接到 URL 参数
}
],
// 默认过滤
defaultFilter: [
{ field: 'build_year', comparator: '==', value: '2021', isDisabledDelete: true }
]
}
])
示例四:自定义闪烁动画
const mapRef = ref()
function startBlink() {
if (!mapRef.value) return
const blinkConfig = {
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [[
[116.35, 39.95], [116.45, 39.95],
[116.45, 39.88], [116.35, 39.88],
[116.35, 39.95]
]]
}
}]
}
},
layer: {
type: 'fill',
layout: {},
paint: {
'fill-color': '#ff0000',
'fill-opacity': 0.8
}
},
blink: {
layerKey: 'paint',
key: 'fill-opacity',
frequency: 3, // 每秒 3 次
minValue: 0.2,
maxValue: 0.9,
often: 5000 // 5 秒后自动停止
}
}
const ctrl = mapRef.value.createCustomBlinkLayer('alarm-1', blinkConfig)
// 可提前手动停止
// ctrl.stop()
}
示例五:批量要素闪烁(查询结果高亮)
const mapRef = ref()
function highlightSearchResults() {
if (!mapRef.value) return
mapRef.value.startBatchBlink(
[
{
layerId: 'explorationRight',
featureIds: ['id1', 'id2', 'id3'],
attrKey: 'dsid'
},
{
layerId: 'miningRight',
featureIds: ['id4'],
attrKey: 'dsid'
}
],
{
duration: 1000, // 每次闪烁 1 秒
blinkTimes: 5, // 闪烁 5 次后自动停止
flyTo: true, // 先飞行到要素范围
visibleRange: 100 // 如果要素已在视口 100px 内则不飞行
}
)
}
function stopAllBlink() {
mapRef.value?.stopBatchBlink()
}
示例六:插入自定义面板(插槽)
<template>
<div class="map-wrap">
<GisMapLibre
ref="mapRef"
:config-state="configState"
:map-config="mapConfig"
:split-config="splitConfig"
@init-complete="onMapInit"
>
<!-- 左侧面板:自定义图层管理器 -->
<template #gitLeft>
<div class="custom-left-panel">
<h3>自定义面板</h3>
<p>这里可以放统计、图表等</p>
</div>
</template>
<!-- 底部面板:分析结果 -->
<template #gisFooter>
<div class="custom-footer-panel">
<h3>分析结果</h3>
</div>
</template>
</GisMapLibre>
</div>
</template>
<script setup lang="ts">
const splitConfig = reactive({
split1: { defaultSize: 0.3, disabled: false, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 },
split2: { defaultSize: 0.4, disabled: false, size: undefined, watchProps: ['defaultSize'], min: 0, max: 1 }
})
const onMapInit = (map: any) => {
console.log('地图就绪,可开始业务逻辑')
}
</script>
构建流程
- Vite 库模式构建 (
vite build --config vite.config.lib.ts):产出es+umd两种格式 - TypeScript 类型生成 (
vue-tsc --project tsconfig.lib.json):生成.d.ts类型声明 - 代码混淆:通过
vite-plugin-javascript-obfuscator进行字符串加密与标识符混淆 - 压缩:通过
terser进行代码压缩,移除所有console.*调用
本地开发与调试
开发目录说明
packages/— 组件库源码。开发时通过@/别名引用(使用vite.config.lib.ts中的 alias 配置)src/— 开发预览目录。src/main.ts是开发入口,src/components/gis/index.vue是主要的演示页面- 修改组件 — 修改
packages/gis-mapliber/中的文件后,热更新即可看到效果
贡献指南
代码规范
- 语言:TypeScript + Vue 3 Composition API(
<script setup>) - 包管理器:pnpm
- 构建:Vite 库模式,入口为
packages/index.ts - 类型:所有新增的 Props、Events、Exposed Methods 必须在类型文件中声明
- 样式:使用 Less 编写,打包后产出
dist/style.css
feat: 新增图层批量闪烁功能
fix: 修复图层删除后 source 未清除的问题
docs: 更新 README.md 组件方法文档
refactor: 重构 useMeasurement composable
chore: 升级 vite 到 5.x
常见问题 (FAQ)
Q1: 地图不显示,一片空白?
A: 检查以下几点:
- 地图容器是否有明确的高度(如
height: 100vh或height: 500px) - 是否引入了样式
import 'gis-maplibre/dist/style.css'(v1.0.8+ 必须手动引入) - 浏览器控制台是否有报错
Q2: overlayLayers 动态 push 后不生效?
A: overlayLayers 必须用 ref() 或 reactive() 包装:
// ✅ 正确
const overlayLayers = ref([])
// ❌ 错误(不会触发响应)
let overlayLayers = []
Q3: splitConfig 修改 disabled 无效?
A: splitConfig 必须用 reactive() 包装:
// ✅ 正确
const splitConfig = reactive({ split1: { disabled: true }, split2: { disabled: true } })
// ❌ 错误
const splitConfig = { split1: { disabled: true }, split2: { disabled: true } }
Q4: 控制台提示 "Pinia is not installed"?
A: 确保在使用 GisMapLibre 之前注册了 Pinia:
// main.ts
import { createPinia } from 'pinia'
app.use(createPinia()) // 必须在 app.use(GisMapLibre) 之前
Q5: 矢量瓦片图层如何配置 source-layer?
A: 在 layers 数组的每个样式对象中指定 'source-layer':
{
type: 'vector',
tiles: ['https://example.com/tiles/{z}/{x}/{y}.pbf'],
layers: [
{
type: 'fill',
layerType: 'fill',
'source-layer': 'buildings', // 矢量瓦片中的图层名
paint: { 'fill-color': '#ff0000' }
}
]
}
Q6: 闪烁动画不工作?
A:
createCustomBlinkLayer— 检查source.type、layer.type是否正确startBatchBlink— 确保图层配置中有promoteId或使用了正确的 source/sourceLayer/id 三元组;检查attrKey的值是否与要素属性中的键对应
Q7: 如何获取地图实例来做自定义操作?
A: 通过 ref 获取组件实例,然后访问 .map 属性:
const mapRef = ref()
// 在 @init-complete 回调中或之后的任意时刻
const mapInstance = mapRef.value?.map
mapInstance?.addSource(...)
mapInstance?.addLayer(...)
也可以直接使用暴露的 maplibregl 和 turf 属性。
Q8: 服务端过滤(isParameter)的工作原理?
A: 当用户修改过滤面板的值时,组件会:
- 收集所有
isParameter: true的过滤条件 - 根据
parameterType拆分为 URL 参数(?field=value)和 SQL WHERE 子句 - 将结果通过
search-layer-filter-data事件传递给父组件 - 父组件负责将参数拼接到实际的瓦片请求 URL 中
Q9: addLayerIsDel 的作用?
A: 当设置为 true 时,每次 overlayLayers 变化(增/删/改),组件会先删除地图上所有已有图层再重新添加。默认 false(增量更新)。如果你的数据源 URL 不变但需要重新加载数据,可设为 true。
Q10: 如何自定义 Naive UI 主题?
A: 在最外层包裹 <n-config-provider> 并传入自定义 theme,或修改 gis-maplibre/dist/style.css 中的 CSS 变量。组件内部的 config-provider 自带 zhCN 和 dateZhCN 本地化配置。
更新日志
v1.0.10
- 稳定版本
v1.0.8
- 样式不再自动注入,需手动引入
import 'gis-maplibre/dist/style.css'
v1.0.0
- 初始发布:基于 MapLibre GL + Vue 3 + Naive UI 的企业级 GIS 组件库
- 支持 GeoJSON、Vector、Raster、Raster-DEM、Image 五种数据源
- 内置图层管理器、搜索过滤、工具栏、图例、测量工具
- 批量闪烁和自定义闪烁动画
- 要素选择(框选/点选/多选)
许可证
Apache-2.0
作者:mayunhui 591878820@qq.com
Related Packages
Nuxt module for vue3-maplibre-gl — auto-import components, composables, CSS, and...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.0.13 | ^3.4.0 | Apache-2.0 | |
| 1.0.12 | ^3.4.0 | Apache-2.0 | |
| 1.0.11 | ^3.4.0 | Apache-2.0 | |
| 1.0.10 | ^3.4.0 | Apache-2.0 | |
| 1.0.9 | ^3.4.0 | Apache-2.0 | |
| 1.0.8 | ^3.4.0 | Apache-2.0 | |
| 1.0.7 | ^3.4.0 | Apache-2.0 | |
| 1.0.6 | ^3.4.0 | Apache-2.0 |