ux-cesium
v0.0.6
Published
基于 Cesium 的地图标绘与点位管理库,支持 Primitive 聚合、动态 Label、弹窗、Plot 标绘、多边形分割合并与键盘漫游。
Maintainers
Readme
ux-cesium
基于 Cesium 的地图标绘与点位管理库,支持 Primitive 聚合、动态 Label、弹窗、Plot 标绘、多边形分割合并与键盘漫游。
安装
pnpm add ux-cesiumPeer 依赖:需在页面中全局引入 Cesium(window.Cesium)并初始化 window.viewer。
快速开始
import {
Plot,
plotConfig,
AddMarker,
DragPoint,
map,
mapConfig,
filterMap,
keyboardMapRoamingInit,
} from 'ux-cesium'
keyboardMapRoamingInit(window.viewer)
AddMarker.add({
list: [{ lng: 114.11, lat: 22.60 }],
name: '视频',
icon: '/icons/camera.png',
})
filterMap(window.viewer, { invertColor: true, filterRGB: [60, 145, 172] })导出 API
| 导出 | 说明 |
|------|------|
| Plot | 标绘主类:绘制、编辑、分割、合并、历史记录 |
| plotConfig | 内置标绘类型配置列表 |
| AddMarker | 点位 / 线 / 面 / 聚合 / 文本 / 弹窗 |
| AddBuffer | 缓冲区域绘制 |
| DragPoint | 拖动可拖拽点位,支持范围限制与自定义校验 |
| map | 地图工具(初始化、飞行、量算等) |
| mapConfig | 地图中心、底图、Provider 等配置 |
| filterMap | 底图色彩滤镜 |
| keyboardMapRoamingInit | 键盘控制相机漫游 |
AddMarker 点位
import { AddMarker } from 'ux-cesium'
// type: billboard | label | text | polygon | polyline | clusterPoint | modal
AddMarker.add({
list: [{ lng: 114.11, lat: 22.60 }],
type: 'billbord',
name: '图层名',
icon: '/icon.png',
config: {},
})
AddMarker.selected(data, config)
AddMarker.get('图层名->id', isData)
AddMarker.del('图层名')
AddMarker.del('图层名->id')
AddMarker.show('图层名', true)聚合点位(PrimitiveCluster)
AddMarker.add({
type: 'clusterPoint',
list: [{ lng: 114.11, lat: 22.60 }],
name: '聚合点',
icon: '/icon.png',
clusterIcon: '/cluster.png',
})跟随文本(type: text)
始终显示在地图上,随相机移动同步更新位置。html 须为 Vue VNode 或 defineComponent,内部通过 createApp 挂载,不支持纯 HTML 字符串。
import { defineComponent, h } from 'vue'
import { NInput } from 'naive-ui'
import { AddMarker } from 'ux-cesium'
AddMarker.add({
type: 'text',
name: 'text-layer',
list: [
{ lng: 114.113, lat: 22.602, html: h('div', {}, '纯文本') },
{ lng: 114.114, lat: 22.604, html: h(NInput, { modelValue: '' }) },
{ lng: 114.115, lat: 22.605, html: h('div', { innerHTML: '<b>富文本</b>' }) },
{ lng: 114.116, lat: 22.606, html: defineComponent({ render: () => h(MyComponent, { foo: 1 }) }) },
],
config: {
margin: { left: 0, top: 0 }, // 相对点位屏幕坐标偏移
transform: 'translate(-50%,-110%)', // CSS transform
},
})也可直接调用 AddMarker.textFn({ list, name, config }),参数与上述一致。
悬浮弹窗(type: modal)
加载 billboard 点位,鼠标悬停点位时展示弹窗,移出弹窗或移开点位后关闭。
import { h } from 'vue'
import { NInput } from 'naive-ui'
import { AddMarker } from 'ux-cesium'
import pointImg from '@/assets/images/plot/火点.png'
AddMarker.add({
type: 'modal',
name: 'quyu-marker', // 点位图层名
icon: pointImg, // 默认图标,单项可设 item.icon
list: [
{ lng: '114.063', lat: '22.532', html: h('div', { class: 'tip' }, '悬停显示') },
{ lng: '114.069', lat: '22.537', html: h(NInput, { modelValue: '' }) },
],
config: {
margin: { left: 0, top: 0 },
transform: 'translate(-50%,-110%)',
},
})
// 删除点位图层(含 hover 监听)
AddMarker.del('quyu-marker')
// 仅删除当前悬浮弹窗(图层名自动为 '{name}-modal')
AddMarker.del('quyu-marker-modal')| 参数 | 说明 |
|------|------|
| name | 点位图层名;弹窗图层自动命名为 {name}-modal |
| list[].lng / list[].lat | 经纬度,必填 |
| list[].html | 弹窗内容,必填,须为 VNode / defineComponent |
| list[].icon | 可选,覆盖默认点位图标 |
| config.margin | 弹窗相对点位屏幕坐标偏移 { left, top } |
| config.transform | CSS transform,默认 translate(-50%,-110%) |
modalFn(单独弹窗)
一般由 type: 'modal' 内部在悬停时自动调用,也可手动指定单个弹窗:
AddMarker.modalFn({
name: 'my-modal',
item: {
lng: 114.113,
lat: 22.602,
html: h('div', {}, '弹窗内容'),
},
config: {
margin: { left: 0, top: 0 },
transform: 'translate(-50%,-110%)',
},
})鼠标移出弹窗时会自动 AddMarker.del(name) 关闭。
html 写法(text / modal 通用)
| 写法 | 是否有效 |
|------|----------|
| h('div', {}, '文字') | ✓ |
| h(NInput, { modelValue: '' }) | ✓ |
| h('div', { innerHTML: '<b>html片段</b>' }) | ✓ |
| defineComponent({ render: () => h('span', {}, '...') }) | ✓ |
| '<div>222</div>' 纯字符串 | ✗ |
h、defineComponent 在 <script setup> 中通常已通过 unplugin-auto-import 自动导入;普通 .js 文件需手动从 vue 引入。
DragPoint 拖动点位
配合 AddMarker.add 使用:列表项需设置 drag: true 才允许拖动。
import { AddMarker, DragPoint } from 'ux-cesium'
// 1. 先添加可拖动点位
AddMarker.add({
name: '火点',
icon: '/images/plot/火点.png',
list: [
{ lng: 114.063, lat: 22.532, drag: true },
{ lng: 114.069, lat: 22.537, drag: true },
],
})
// 2. 启用拖动(默认开启吸附)
const drag = new DragPoint({
viewer: window.viewer,
enableSnap: true,
snapDistance: 20,
snapTypes: ['vertex', 'edge', 'center'],
// 多边形范围:点位序列围成区域,超出则回退到按下时的位置
bounds: [
[114.0, 22.0],
[114.5, 22.0],
[114.5, 22.8],
[114.0, 22.8],
],
// 或 bounds: [{ lng: 114, lat: 22 }, ...]
// 也可传入标绘多边形的 pos 坐标:polygonRow.pos.map(([lng, lat]) => [lng, lat])
// 自定义校验:返回 true 阻止移动并回退
beforeMove({ lng, lat, height, cartesian, start }) {
// start 为拖动起点 { lng, lat, height, cartesian }
return false
},
callback({ lng, lat, height, blocked }) {
// 每次 mousemove 触发;blocked 表示本次是否被 bounds/beforeMove 拦截
},
})
// 运行时更新
drag.setBounds([[114, 22], [115, 22], [115, 23], [114, 23]])
drag.setBeforeMove(({ lat }) => lat > 23)
drag.setBounds(null) // 取消范围限制
drag.setBeforeMove(null) // 取消自定义校验
// 销毁(移除鼠标监听)
drag.updateAction()| 参数 / 方法 | 说明 |
|-------------|------|
| bounds | 多边形顶点数组,至少 3 点,首尾自动闭合 |
| beforeMove | 返回 true 阻止移动并回退到起点 |
| enableSnap | 是否吸附其他图形顶点,默认 true |
| callback | 拖动过程坐标回调,含 blocked 字段 |
| setBounds(points) | 动态设置/清除多边形范围 |
| setBeforeMove(fn) | 动态设置/清除校验函数 |
| updateAction() | 销毁实例,释放事件与吸附资源 |
Plot 标绘
基础用法(参考 PlotPanel.vue)
import { Plot, plotConfig } from 'ux-cesium'
const defaultConfig = {
pointSize: 1,
textColor: '#fff',
textSize: 16,
style: 'solid',
color: '#BCA00D',
borderColor: 'red',
borderSize: 4,
labelShow: true,
alpha: 0.2,
}
const plotData = ref([])
// 点击工具栏开始绘制
function plotClick(item) {
new Plot({ ...defaultConfig, ...item }, (e) => {
plotData.value.unshift(e.getData())
})
}
// 载入已有数据
function showData() {
const parent = window.viewer.entities.getOrCreateEntity('父实体-可有可无')
plotData.value.forEach(async (item) => {
const plot = await Plot.toData(item, null)
plot.addDraw.parent = parent
})
}
// 点击地图进入编辑
function initEditClick() {
const handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas)
handler.setInputAction((evt) => {
const pick = window.viewer.scene.pick(evt.position)
if (pick?.id?.objId || pick?.id?.startsWith('plot')) {
const row = plotData.value.find(
(o) => o.config.objId === pick.id?.objId || pick.id === o.config.objId,
)
if (!row) return
Plot.edit({ curData: row, moveMultiple: true }, () => {
plotData.value = plotData.value.filter((o) => o.config.objId !== row.config.objId)
})
} else {
Plot.edit({ hide: true })
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}
// 删除
Plot.clear(objId)多边形编辑(参考 PolygonEdit.vue)
支持绘制、分割、合并、覆盖删除、撤回重做、顶点吸附、多选编辑。
import { Plot } from 'ux-cesium'
const plotData = ref([])
const historyManager = ref(Plot.createHistoryManager(50))
let curSelPlot = []
// 绘制多边形
function drawPolygon() {
new Plot(
{ type: 'polygon', double: true, color: 'red', alpha: 0.6, borderColor: 'red' },
async (e) => {
await Plot.executeWithHistory(
historyManager.value,
plotData,
() => {
plotData.value.unshift(e.getData())
return Promise.resolve()
},
'绘制图形操作',
'draw',
)
},
)
}
// 分割:先选中目标多边形,再绘制 brokenLine 折线
async function splitPolygon(splitLineData) {
await Plot.executeWithHistory(
historyManager.value,
plotData,
() => {
const result = Plot.performPolygonSplit(
plotData, curSelPlot, splitLineData, defaultConfig, configs, showData,
)
return result.success
? Promise.resolve(result)
: Promise.reject(new Error(result.message || '分割失败'))
},
'分割多边形操作',
'split',
)
}
// 合并:Ctrl 多选至少 2 个多边形
async function mergePolygon() {
await Plot.executeWithHistory(
historyManager.value,
plotData,
() => {
const result = Plot.performPolygonUnion(plotData, curSelPlot, defaultConfig, configs, showData)
return result.success ? Promise.resolve(result) : Promise.reject(new Error(result.message))
},
'多边形合并操作',
'merge',
)
}
// 覆盖删除:选中 1 个多边形作为边界
async function coverageDelete() {
await Plot.executeWithHistory(
historyManager.value,
plotData,
() => {
const result = Plot.performCoverageDelete(plotData, curSelPlot, defaultConfig, configs, showData)
return result.success ? Promise.resolve(result) : Promise.reject(new Error(result.message))
},
'覆盖删除操作',
'coverage_delete',
)
}
// 进入编辑(点击图层或地图 pick)
function editRow(row, { ctrlKey = false, hide = false } = {}) {
Plot.edit({
curData: row,
allData: plotData.value,
multiEdit: ctrlKey, // Ctrl 多选编辑
hide, // true 时隐藏编辑点
moveMultiple: true, // 整体移动
insertPoint: true, // 边中点虚拟点
enableSnap: true,
snapConfig: {
snapDistance: 20,
snapTypes: ['vertex', 'edge', 'center'],
showSnapIndicator: true,
},
historyManager: historyManager.value,
}, () => {
plotData.value = plotData.value.filter((o) => o.config.objId !== row.config.objId)
})
}
// 撤回 / 重做
const { canUndo, canRedo } = Plot.getUndoRedoState(historyManager.value)
async function undo() {
await Plot.simpleUndo(historyManager.value, plotData, showData, clearAll)
}
async function redo() {
await Plot.simpleRedo(historyManager.value, plotData, showData, clearAll)
}
function clearAll() {
plotData.value.forEach((item) => Plot.clear(item.config.objId))
}Plot.edit 参数
| 参数 | 说明 |
|------|------|
| curData | 当前编辑的标绘数据 |
| allData | 全部标绘列表(删除时用) |
| moveMultiple | 启用整体移动 |
| insertPoint | 边中点虚拟点,可拖动插入顶点 |
| multiEdit | Ctrl 多选模式 |
| enableSnap | 顶点吸附 |
| snapConfig | 吸附距离、类型等 |
| historyManager | 历史记录管理器,拖动/删除自动入栈 |
| hide | 隐藏编辑控制点 |
Plot 多边形静态方法
| 方法 | 说明 |
|------|------|
| Plot.performPolygonSplit | 折线分割多边形 |
| Plot.performPolygonUnion | 合并多个多边形 |
| Plot.performCoverageDelete | 覆盖删除 |
| Plot.createHistoryManager | 创建历史管理器 |
| Plot.executeWithHistory | 包装操作并自动保存历史 |
| Plot.simpleUndo / Plot.simpleRedo | 撤回 / 重做 |
| Plot.getUndoRedoState | 获取按钮可用状态 |
常用 type:drawPoint、line、polygon、brokenLine(分割线)、rect、circle、arrow 等,完整列表见 plotConfig。
map 工具
import { map, mapConfig } from 'ux-cesium'
// 初始化地图
map.initCesiumMap({ ...mapConfig.mapProviderConfig[1], extendConfig: {} }, 1, () => {
// viewer 就绪回调
})
map.flyTo({ lng: 114.2, lat: 22.5, height: 5000 })filterMap 底图滤镜
import { filterMap } from 'ux-cesium'
filterMap(window.viewer, {
invertColor: true,
filterRGB: [60, 145, 172],
brightness: 0.6,
contrast: 1.8,
})keyboardMapRoamingInit
| 按键 | 功能 | |------|------| | W / S / A / D | 前 / 后 / 左 / 右 | | Q / E | 升 / 降 | | ↑ ↓ ← → | 抬头 / 低头 / 左转 / 右转 | | + / - | 放大 / 缩小 |
本地开发
pnpm install
pnpm dev # 演示项目(PlotPanel / PolygonEdit 组件)
pnpm build # 打包库(入口 src/lib/main.ts)目录
src/
├── lib/main.ts # 库导出入口
├── plot/ # 标绘、点位、聚合
├── map/ # 地图工具与配置
└── components/
├── PlotPanel.vue # 基础标绘演示
└── PolygonEdit.vue # 多边形分割/合并/历史记录演示