更新记录
1.3.0(2026-10-08) 下载此版本
1.3.0(2026-10-08)
面向「设备点位查看 + 坐标标注」补齐点位表现与交互(对照 web 端 gisfactory 的点位特性清单):
- breaking:组件目录与标签改名为
yolo-gis——components/gis-map/gis-map.vue(标签<gis-map>)→components/yolo-gis/yolo-gis.vue(标签<yolo-gis>);组件name由GisMap改为YoloGis,诊断日志前缀[GisMap]→[YoloGis],DOM class / id 前缀gis-map__*→yolo-gis__*。原因:插件市场按插件 id 校验components/<插件id>/目录,原目录名会导致上传报「插件包指定目录 components/yolo-gis 不存在」。页面需同步 import 路径与标签(easycom 标签同步改为<yolo-gis>)。 - 点位朝向旋转:markers 新增
deviationAngle(摄像机监控朝向角),按 22.5° 一档量化后旋转图标(与 web 端angleArray一致);开启marker-rotatable后枪机图标拆成「底座 + 字模」两层,旋转只作用于字模,蓝底徽标与底部针脚保持不动(未开且无朝向角时仍是单张图标,零额外开销)。 - 告警动图 + 超量降级:
type: 'alarm'走告警 GIF(static/icons/gis/alarm/anime_alart.gif,与 web 端同源资源);同屏动图超过 10 个自动降级为静态图(ico_alarm.png)+ CSS 红圈脉冲 —— 动图解码开销大,密集告警页防卡顿,降级时控制台打一行日志。 - 气泡多按钮:
markers[].popup.actions = [{ key, text }]渲染成气泡底部按钮排,点击抛popup-action({ marker, actionKey })由页面决定跳转(如「实时视频」「通行记录」);未配actions时保留原popup-action-text单行提示 + 整泡popup-click,向后兼容。 - 选中态:新增
selected-id—— 蓝色描边环持久框住选中点位(与瞬时focus-point脉冲互不冲突),只切 class 不重画点位、全量重画后自动恢复,按id或deviceId匹配;用于「列表点选 ↔ 地图高亮」联动。 - 点位拖动标注:新增
draggable-marker-id+marker-dragend事件({ data, lng, lat })—— 指定点位可拖动(跟手),松手抛新坐标,由页面决定是否保存(设备地图标注页用)。 - 朝向角调整:新增
marker-rotate({ id, deg })—— 增量调整某个点位朝向角,不重画整层点位(标注页滑杆实时预览用)。 - GPS 定位与内置定位钮:新增
show-location(GPS 能力 +locate()方法 + 地图「我的位置」蓝点)、show-locate(内置定位钮:点一下去我的位置、再点回预设中心)、tools-direction/tools-top/tools-right/tools-style(工具组排列与位置,可挂到跟手面板上);新增事件location-change/location-error;蓝点为内联 SVG,不依赖图片资源。 hide-popup-on-map-tap:点地图空白处是否收起气泡(默认true;传false时页面可在map-click里做联动、同时保留气泡)。- 修复两处定位交互:① 页面
focus-point与内置定位钮的飞行改为独立通道 —— 此前合并成一个字段时,页面的 focusPoint 会压住定位钮的飞行(表现为「按钮状态变了、地图不动」);② 定位钮状态(视野是否在我位置)判定加 120ms 防抖 —— 一次飞行会先后触发zoomend/moveend,中间过渡态会让状态抖一下、日志连打两条。 - 新增
js_sdk/my-location.js:getMyLocation/myLocationMarkerOf/LOCATION_ICON(GPS 获取 + 「我的位置」点位生成)。 marker-style.js:新增cameraRotation(deviationAngle)(22.5° 量化)、resolveMarkerSymbol输出markerRotate、DEVICE_TYPE_NAMES类型名表;新增枪机字模static/icons/gis/glyph/ico_qiangji_glyph.png与底座static/icons/gis/on/ico_qiangji_base.png。
定位能力需在 App 端授予定位权限(
show-location/show-locate打开后组件通过plus请求);H5 端受浏览器定位权限与 HTTPS 限制。
1.2.1(2026-09-17)
-
气泡可点:新增
popup-action-text属性(气泡底部操作提示行,非空时可点)与popup-click事件(回传该点位业务数据),用于「点气泡 → 底部操作条」这类交互;气泡点击已stopPropagation,不会误触地图map-click。 -
注释瘦身(只动注释,代码零改动):去掉叙述性踩坑长文与复述代码的注释,保留「为什么这么写」的关键一行。注释占比从 17~45% 降到 8~17%(
gis-map.vue590→466 行、注释 151→62 行;dom-marker-layer.js448→406 行)。 -
useGisScene支持宿主已有楼层数据,不再强制请求接口(三种来源,优先用已有的):mapVo:项目已确定当前楼层(告警联动、单层地图页)→ 直接建图,连楼层下拉树都不需要floors:项目登录/初始化已缓存楼层数组(数组 / ref / getter 均可)→ 用缓存建下拉树,零请求loadFloors:都没有时提供取数函数(内部只调用一次)
-
自动初始化:
useGisScene默认自己准备楼层并取首批点位,页面无需手动调用loadFloors()(autoInit: false可关,改由页面控制时机)。 -
请求去重:初始化与「楼层变化自动重取」共用一个楼层去重键,同一楼层不会重复请求;需要强制刷新用
scene.reload()。 -
文档去宿主化:readme 的「快速使用」不再出现宿主项目 API,改为通用组件文档 —— 附
mapVo字段契约(★ 标注必需字段)与 markers 结构;「业务接入流程」的示例改用中性占位(yourApi.*),并补充「楼层数据三种来源」对照表;web 端参数对照表加了「纯移动端项目可忽略」说明。 -
readme 按「使用顺序」重排:目录从「教程 + 手册混排」改为 11 节顺序阅读 —— ①最小接入(3 步)→ ②页面完整示例 + 调用顺序表(①取楼层 → ②
useGisScene→ ③筛选栏 → ④v-bind="scene.markersProps"→ ⑤事件 → ⑥切楼层自动重取 → ⑦focus-point)→ ③数据来源 → ④组件 API → ⑤能力开关 → ⑥场景与工具 → ⑦使用须知 → ⑧排障 → ⑨已弃用 → ⑩目录结构 → ⑪规划;新增「阅读顺序」导航表与「排障」日志对照表([GisMap]各日志的含义与下一步)。 -
useGisScene返回值改为reactive:内部 ref/computed 在属性访问时自动解包,页面/模板可直接写scene.markersProps、scene.filterColumns,不再需要scene.xxx.value(示例页已同步简化)。旧写法scene.xxx.value会失效,属配套变更。 -
宿主项目配套改动(不在插件内):
config store增mapFloors缓存,utils/system/systemCache.js → initCache()登录后并行预取有权限的楼层数据(与 web 端initFloor思路一致,失败不阻塞登录);两个 demo 页改为「优先读缓存、缺失再请求并回填」。
1.2.0(2026-09-17)
面向业务做的一轮「参数化 + 流程化」改进(对照 web 端 gisfactory / basegis 的能力清单):
- 组件新增业务参数(都是不同项目/页面会有差异的开关):
manage-mode:管理模式,图标统一用在线样式(对齐 web 端gisCommon.isGisManage,设备标注类场景)show-badge+marker-style.resolveBadge:设备等级/业务类型角标(deviceLevel1→H红/2→Z橙/3→P绿,operationType1→P灰/2→Q蓝/3→A紫,摄像机带业务类型显示双字母;对齐 web 端getCameraBadgeSymbols)cluster+cluster-pixels:点聚合(屏幕像素距离分组、数字气泡、点击放大;阈值默认 50px 与 web 端一致)focus-point:受控定位({ id }/{ lng, lat }),平移到位 + 脉冲高亮(告警联动、搜索跳转)marker-scale:点位尺寸缩放;show-popup:关闭内置气泡(统一走页面 DetailPopup 时用)
- 新增
js_sdk/marker-adapter.js(业务适配层):normalizeDevice(兼容deviceId/device_id、longitude/lng、isOnline/is_online、accessStatus/access_status、deviceLevel/device_level等命名差异)、toDeviceMarkers、toAlarmMarkers(自动过滤无坐标点位、自动生成气泡摘要字段)、devicePopupFields、summarizeMarkers。气泡只放摘要(不依赖字典),完整字段仍由页面 DetailPopup 渲染。 - 新增
js_sdk/map-scene.js(场景编排层):useGisScene({ scene, loadFloors, loadPoints, componentProps })把「楼层树 → 筛选 → 取数 → 转点位 → 组件参数」串成一条流程,返回markersProps可直接v-bind给组件;SCENE_PRESETS提供device / deviceManage / alarm / dense四套场景预设,sceneProps(scene, overrides)支持单项覆盖。 - 示例页:新增
pages/demo/map/GisMapScene.vue(真实楼层树 + 模拟点位,四种场景一键切换、参数实况展示、focus-point演示、点击走 DetailPopup),演示「自定义传参后使用」的完整接法。 - 文档:readme 新增「业务接入流程」章节(三层结构、接入 5 步、场景参数表、adapter 用法、web 端参数 → 移动端属性对照表)。
1.1.0(2026-09-17)
- breaking:彻底移除 canvas 矢量层点位渲染,点位与气泡固定走 DOM 渲染(详见踩坑 8、9)。移除了
marker-render属性与配套的强制合成、自愈重建、资源预加载、渲染时序埋点等一整套兜底代码。 - breaking:组件改名为
GisMap,路径components/yolo-gis-map/yolo-gis-map.vue→components/gis-map/gis-map.vue(easycom 标签<gis-map>)。原<yolo-gis-map>标签不再可用,使用import GisMap from '@/uni_modules/yolo-gis/components/gis-map/gis-map.vue'或直接写<gis-map>。 - 新增:气泡指向图标的小尖角,并处理贴边:上方放不下自动翻到点位下方;左右贴边整体收进屏幕且尖角仍对准点位。
- 新增:
auto-center-marker(默认true):点击点位后平移到地图中心(等价 InfoWindow autoPan),已在中心附近时不移动。 - 新增:门禁开关门状态(
door-status,默认false):与 web 端resVisualization传iconResolver同规则 —— 门禁(deviceType: '02')带accessStatus(1 开门 / 其他关门)时用开关门图标(static/icons/gis/access/open_door.png、close_door.png,与 web 端同源资源)。有的项目需要、有的不需要,故默认关闭(关闭时门禁仍按常规在离线/故障图标显示);resolveAccessDoorIcon(m)已从marker-style.js导出,页面也可直接复用。 - 图标比例修正:插件图标统一为 28x38,此前
resolveMarkerSymbol默认返回markerHeight: 28会把图标压扁;现改为未显式指定高度时由渲染层按图片原始比例自适应(height: auto)。 - 重构:内部按职责拆分为 js_sdk 模块 —— 新增
map-env.js(maptalks 加载 / 容器尺寸钉整数 / 图标地址解析 / 切片自检)、dom-marker-layer.js(DOM 点位层:渲染/定位/气泡/居中);组件壳只保留 props/emits 与 renderjs 地图生命周期。对外仍只有一个组件入口。 - 诊断日志精简:仅保留环境能力、容器尺寸、切片连通性、点位渲染数量、图标加载失败等有用信息。
1.0.0(2026-09-15)
- 首个版本:yolo-gis-map 组件,renderjs 承载 maptalks 1.4.6(npm 依赖)
- 自建 XYZ 切片底图(EPSG:3857,与 web 端 gisfactory bmap 分支一致)、点位标记、marker-click / map-click 事件、mapVo 变化重建地图
- 内置排障日志:observer 心跳、切片连通性自检、瓦片加载事件
平台兼容性
uni-app(3.8.5)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | √ | √ | √ | × | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
yolo-gis maptalks 地图
maptalks 1.6.1 地图组件,对外只暴露一个组件 YoloGis(easycom 标签 <yolo-gis>),通过 renderjs 承载,与项目里 qiun-data-charts(echarts)同一套机制。能力:自建 XYZ 切片底图、多设备状态图标、门禁开关门、设备等级角标、点聚合、受控定位、DOM 点位与气泡;点位侧支持监控朝向旋转、告警动图(超量自动降级)、气泡多按钮、选中高亮、拖动标注取坐标,以及 GPS 定位 + 内置定位钮。
库的加载方式:UMD 构建随插件分发(
static/maptalks.min.js,官方文件原样未改),renderjs 里动态注入<script>加载并挂window.maptalks单例 —— 与 qiun-data-charts 加载 echarts.min.js 完全一致,项目无需任何 npm 依赖。 不要改成静态 import(无论 npm 包还是插件内相对路径):鸿蒙端 renderjs 编译会把库内联进多个模块实例,触发 maptalks 官方「Disallow duplicate imports」保护(执行即 throw),连锁导致 renderjs 模块注册失败(module gis not found)。
兼容性
| 平台 | 支持 | 原因 |
|---|---|---|
| App(vue 页面) | ✅ | WebView 渲染,renderjs 可用 |
| H5 | ✅ | renderjs 自动降级;跨域切片需代理或服务端放行 |
| 各家小程序 | ❌ | 双线程模型拿不到 DOM,DOM 地图库无法运行(平台限制,无法绕过) |
阅读顺序
| 想知道什么 | 看哪节 |
|---|---|
| 页面里怎么写、先调哪个再调哪个 | 一、最小接入 → 二、页面完整示例(调用顺序表) |
| 楼层数据 / 点位数据从哪来 | 三、数据来源 |
| 有哪些属性、事件、markers 字段 | 四、组件 API |
| 门禁开关门 / 角标 / 聚合 / 定位 | 五、能力开关 |
| 朝向旋转 / 告警动图 / 气泡多按钮 / 选中高亮 / 拖动标注 | 五、能力开关 |
| 换业务场景(设备地图、告警、密集) | 六、场景与工具 |
| 报错、图标不显示、切片不出来 | 七、使用须知 / 八、排障 |
一、最小接入(只用组件,3 步)
① 引入组件
<!-- 方式一:easycom 自动注册,直接写标签(无需 import)—— 推荐 -->
<yolo-gis :map-vo="mapVo" :markers="markers" :fit-markers="true" />
// 方式二:显式 import(变量名随意,常用 YoloGis)
import YoloGis from '@/uni_modules/yolo-gis/components/yolo-gis/yolo-gis.vue'
组件目录
components/yolo-gis/与插件 id 同名(插件市场按此校验),标签<yolo-gis>;js_sdk的引入路径为@/uni_modules/yolo-gis/js_sdk/xxx.js。
② 准备 mapVo(楼层地图配置)
// ★ 为组件必需字段,其余可选
const mapVo = {
floorCode: 'F1', // ★ 楼层标识(变化即销毁重建地图)
mapServiceUrl: 'http://host/mapfile/jn/out', // ★ XYZ 切片地址(拼 /{z}/{x}/{y}.png)
centerLongitude: 117.0038439, // ★ 初始中心经度
centerLatitude: 42.0028326, // ★ 初始中心纬度
baseLevel: 19, // ★ 初始层级
minZoom: 15, // 可选,缩放范围
maxZoom: 22, // 可选
}
③ 准备 markers(点位数组)
const markers = [
{ id: 'd1', lng: 117.0034, lat: 42.0031, deviceType: '01', ptzType: '01', isOnline: '1' },
]
字段含义见「四、组件 API → markers 结构」。
④ 写模板 + 接事件
<view class="map-box"> <!-- 必须给高度,见「七、使用须知」第 4 条 -->
<yolo-gis
:map-vo="mapVo"
:markers="markers"
:fit-markers="true"
loading-text="底图切片加载中…"
@ready="onReady"
@marker-click="onMarkerClick"
@map-click="onMapClick"
/>
</view>
到这里地图就能出来。只用组件时的调用顺序很简单:
| 顺序 | 做什么 | 何时触发 |
|---|---|---|
| ① | 给 map-vo |
页面初始化 |
| ② | 给 markers |
同上(拿到接口数据后赋值即可) |
| ③ | 地图自动创建 | 组件内部(无需页面干预) |
| ④ | ready |
地图与底图就绪(此后才能做定位) |
| ⑤ | marker-click / map-click |
用户点击 |
| ⑥ | 换 map-vo = 换楼层 |
组件内部自动销毁重建,不需要重新赋值 markers(会一起更新) |
二、页面完整示例(推荐:用编排层,流程有固定顺序)
js_sdk/map-scene.js 的 useGisScene 把「楼层 → 筛选 → 取数 → 转点位 → 组件参数」串成一条线,页面按下面 6 步写即可。
完整文件(可直接抄,改接口即可)
<template>
<view>
<!-- ③ 筛选栏:楼层 + 设备状态(columns 由流程给出) -->
<DropdownFilter :columns="scene.filterColumns" @change="scene.onFilterChange" />
<!-- ④ 地图:v-bind 展开流程产物 -->
<view class="map-box">
<yolo-gis
v-bind="scene.markersProps"
:focus-point="focusPoint"
loading-text="底图切片加载中…"
@ready="onReady"
@marker-click="onMarkerClick"
/>
</view>
<!-- ⑤ 页面自己的详情弹窗(组件气泡只做摘要) -->
<DetailPopup v-model="detailShow" :title="detailTitle" :fields="detailFields" mode="bottom" />
</view>
</template>
<script setup>
import { ref } from 'vue'
import { useGisScene } from '@/uni_modules/yolo-gis/js_sdk/map-scene.js'
import { useConfigStore } from '@/store'
/* ── ① 楼层数据:项目登录初始化已缓存,直接给 ── */
const configStore = useConfigStore()
/* ── ② 建流程:楼层 → 取数 → 点位 → 组件参数(内部自动初始化) ── */
const scene = useGisScene({
scene: 'device', // 'device' 设备 / 'alarm' 告警
floors: () => configStore.mapFloors, // 已有缓存:零请求
loadPoints: ({ floorCode }) => api.listDevices({ floorCode }), // 页面自己的接口
componentProps: { doorStatus: true }, // 覆盖场景预设(可选)
})
/* ── ⑤ 事件:点击点位 → 页面弹详情 ── */
const detailShow = ref(false)
const detailTitle = ref('')
const detailFields = ref([])
function onMarkerClick(m) {
detailTitle.value = m.name || m.deviceName || ''
detailFields.value = [{ label: '编号', value: m.deviceNo || '' }]
detailShow.value = true
}
/* ── ⑥ 受控定位:改 focusPoint 即平移 + 脉冲高亮(告警联动/搜索跳转) ── */
const focusPoint = ref(null)
function onReady() { /* 地图就绪,此时才可以 focusPoint */ }
</script>
<style scoped>
.map-box { width: 100%; height: 640rpx; overflow: hidden; }
</style>
调用顺序表(先做什么、后做什么)
| 顺序 | 在哪 | 调用 | 说明 / 为什么在这个位置 |
|---|---|---|---|
| ① | setup 顶部 |
取楼层数据(优先读缓存) | 只取数据不发请求;缓存缺失时由下一步兜底 |
| ② | setup |
useGisScene({...}) |
内部依次做:楼层 → 建楼层下拉树 → 自动初始化取首批点位 → 转 markers → 组装 markersProps。默认自动跑,页面不用手动调 loadFloors() |
| ③ | 模板 | <DropdownFilter :columns="scene.filterColumns" @change="scene.onFilterChange" /> |
楼层/状态筛选栏;filterColumns 由流程给出,不用自己拼 |
| ④ | 模板 | <yolo-gis v-bind="scene.markersProps" /> |
地图自动创建;mapVo 一变组件内部销毁重建(换楼层不需要额外代码) |
| ⑤ | @marker-click |
页面弹 DetailPopup |
组件内置气泡只放摘要,完整字段由页面用字典渲染 |
| ⑤' | @ready |
之后才能用 focus-point |
ready 之前地图还没就绪,定位无效 |
| ⑥ | 用户切楼层 | onFilterChange → 流程内部自动重新取点位 |
同一楼层不会重复请求;需要强制刷新用 scene.reload() |
| ⑦ | 收到告警推送 | 改 focusPoint = { id } 或 { lng, lat } |
传新对象即触发一次定位 + 高亮 |
想自己控制时机(别自动跑)
const scene = useGisScene({ autoInit: false, /* … */ })
onMounted(() => scene.loadFloors()) // 自己决定何时开始
useGisScene 参数与返回
| 参数 | 说明 |
|---|---|
mapVo / floors / loadFloors |
楼层数据三种来源,优先用已有的(见「三、数据来源」) |
loadPoints |
必填,({ floorCode, filters, mapVo }) => Promise<rows[]> |
scene |
'device'(默认)/ 'alarm',决定用哪个适配器与预设 |
deviceType |
设备类型(图标与筛选用) |
componentProps |
覆盖场景预设(如 { doorStatus: true }) |
popup / filter / fields / extraColumns |
气泡开关 / 点位过滤 / 追加气泡字段 / 额外筛选列 |
autoInit |
默认 true:自动准备楼层并取首批点位;false 则手动调 loadFloors() |
autoLoad |
默认 true:自动取首批点位 |
watchMapVo |
默认 true:楼层变化自动重新取点位 |
返回值:{ loading, error, floors, filterValue, mapVo, markers, filteredMarkers, stats, filterColumns, markersProps, loadFloors, reload, }。
三、数据来源
楼层数据(三选一,命中前者就不再请求接口)
| 传入 | 适用情况 | 行为 |
|---|---|---|
mapVo |
项目已确定当前楼层(告警联动、单层地图页) | 直接建图,连楼层下拉树都不需要 |
floors |
项目登录/初始化已缓存楼层数组(数组 / ref / getter 均可) | 用缓存建下拉树,零请求 |
loadFloors |
项目没有楼层缓存 | 调用一次取数函数(建议把结果回填 store 供其他页面复用) |
推荐做法:登录初始化时拉一次楼层,缓存进 store,之后所有页面直接读 —— 避免每页重复请求(web 端
initFloor → appStore.floorMap就是这个思路)。
js_sdk/map-service.js 提供纯工具(不联网):getMapVoList(筛出可建图楼层)、getMapVoByFloorCode(按楼层码取配置)、getDefaultMapVo、groupByBuilding(按楼栋分组做下拉树)。
点位数据(业务行 → markers)
import { toDeviceMarkers, toAlarmMarkers, summarizeMarkers } from '@/uni_modules/yolo-gis/js_sdk/marker-adapter.js'
const markers = toDeviceMarkers(list, { deviceType: '01', popup: true }) // 设备列表 → 点位
const alarms = toAlarmMarkers(alarmList) // 告警列表 → 点位
const stats = summarizeMarkers(markers) // 在线/离线/故障/告警 数量
- 字段自动归一:
deviceId|device_id|id、longitude|lng、isOnline|is_online、accessStatus|access_status、deviceLevel|device_level等 - 自动过滤无坐标数据(与 web 端一致)
- 气泡只放摘要(在线/故障/开关门/楼层/地点/坐标,不依赖字典);完整字段由页面
DetailPopup+ 字典渲染
四、组件 API
属性
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
map-vo |
Object | null | 楼层地图配置;变化时销毁重建地图 |
markers |
Array | [] | 点位数组,见下 |
fit-markers |
Boolean | false | 点位变化时自动缩放视野包含全部点位 |
center |
Array | null | 受控视野中心 [lng, lat] |
zoom |
Number/String | null | 受控层级(默认用 mapVo.baseLevel) |
auto-center-marker |
Boolean | true | 点击点位后把该点位移到地图中心(等价 autoPan),已在中心附近时不动 |
door-status |
Boolean | false | 是否用门禁开/关门图标(见「五、能力开关」);关闭时门禁按常规设备图标显示 |
manage-mode |
Boolean | false | 管理模式:图标统一用「在线」样式,不区分在线/离线(对齐 web 端 isGisManage) |
show-badge |
Boolean | false | 设备等级/业务类型角标(deviceLevel 1→H红/2→Z橙/3→P绿;operationType 1→P灰/2→Q蓝/3→A紫,摄像机带业务类型时显示双字母) |
marker-scale |
Number | 1 | 点位尺寸缩放(基准 28×38,高度按图片比例自适应) |
cluster |
Boolean | false | 点聚合(屏幕像素距离分组,聚合点显示数量、点击放大) |
cluster-pixels |
Number | 50 | 聚合阈值(像素,与 web 端 clusterByPixelDistance 一致) |
show-popup |
Boolean | true | 是否显示内置气泡;页面统一走 DetailPopup 时传 false(点击仍抛 marker-click) |
popup-action-text |
String | '' | 气泡底部操作提示文案(如「点击查看操作」):非空时气泡可点,点击抛 popup-click(做「点气泡 → 底部操作条」用);配了 markers[].popup.actions 时本文案不显示 |
hide-popup-on-map-tap |
Boolean | true | 点地图空白处是否收起气泡;传 false 时页面可在 map-click 里做联动、同时保留气泡 |
focus-point |
Object | null | 受控定位:{ id } 或 { lng, lat },传入即平移到位 + 脉冲高亮 |
selected-id |
String/Number | '' | 选中态:持久高亮描边环(列表↔地图联动),按 id/deviceId 匹配,传 '' 清除;与 focus-point 脉冲互不冲突 |
draggable-marker-id |
String/Number | '' | 拖动标注:指定点位可拖动(跟手),松手抛 marker-dragend 回传新经纬度;传 '' 全部不可拖 |
marker-rotate |
Object | null | 朝向角调整:{ id, deg } 增量旋转该点位图标,不重画整层(标注页滑杆预览用) |
marker-rotatable |
Boolean | false | 允许调摄像机朝向(标注页开):枪机图标拆「底座 + 字模」,旋转只作用字模,徽标与针脚不动 |
show-location |
Boolean | false | 启用 GPS:暴露 locate() 方法,定位成功后地图落下「我的位置」蓝点 |
show-locate |
Boolean | false | 显示内置「我的位置」钮:点一下 → 定位并瞬移到我的位置;再点 → 瞬回 mapVo 预设中心(开启后无需再传 show-location) |
tools-direction |
String | 'vertical' | 工具组排列方向:vertical 竖排 / horizontal 横排 |
tools-top |
Number/String | 20 | 工具组距容器上边距(rpx) |
tools-right |
Number/String | 20 | 工具组距容器右边距(rpx) |
tools-style |
Object | null | 工具组自定义定位样式(传了即接管 tools-top/right),如 { right:'24rpx', bottom:'52px', opacity:1 } 挂到跟手面板 |
loading-text |
String | '地图加载中…' | 未就绪时的占位文案 |
directory |
String | '/' | H5 站点子路径(拼 maptalks.min.js 地址用,App 端不用传) |
事件
| 事件 | 载荷 | 说明 |
|---|---|---|
ready |
— | 地图与底图就绪 |
marker-click |
该点位的业务数据原样对象 | 点击点位 |
popup-click |
该点位的业务数据原样对象 | 点击气泡(配合 popup-action-text 使用,如打开底部操作条) |
popup-action |
{ marker, actionKey } |
点击气泡内按钮(popup.actions 配置项),页面按 actionKey 决定跳转 |
marker-dragend |
{ data, lng, lat } |
拖动点位结束(draggable-marker-id 指定),新坐标由页面决定是否保存 |
location-change |
{ longitude, latitude, accuracy } |
定位成功(show-location / show-locate 开启) |
location-error |
错误对象 | 定位失败(权限拒绝 / 无信号),可提示用户 |
map-click |
{ lng, lat } |
点击地图空白处 |
markers 结构
{
id, lng, lat, // 必填
deviceType, ptzType, // 设备类型/云台类型 → 自动匹配图标
isOnline, deviceStatus, type, // 状态('0' 离线 / deviceStatus≠'9001' 故障 / type:'alarm' 告警动图)
accessStatus, // 仅门禁:1 开门 / 其他关门(需 door-status 开启才生效)
deviationAngle, // 摄像机监控朝向角(0~360),图标按 22.5° 一档旋转
icon, iconWidth, iconHeight, // 自定义图标(优先级最高):http(s) / data:image / /static/... / /icons/gis/...
data, // 业务数据,marker-click 原样回传
popup: {
title, // 气泡标题
fields: [{ label, value }], // 气泡字段行
actions: [{ key, text }], // 气泡底部按钮(点击抛 popup-action,最多 3 个)
}
}
图标优先级:显式 icon > 门禁开关门图标(door-status 开启时,按 accessStatus)> 设备图标(deviceType/ptzType + 状态,切图见 static/icons/gis/)> 状态圆点兜底。
五、能力开关
门禁开关门状态(按需开启)
门禁(deviceType: '02')除在线/离线/故障外还有开/关门状态,有的项目要看、有的不看,故做成显式开关,默认关闭:
<yolo-gis :map-vo="mapVo" :markers="markers" :door-status="true" />
{ name: '门禁(开门)', deviceType: '02', accessStatus: 1 }
{ name: '门禁(关门)', deviceType: '02', accessStatus: 0 }
| 场景 | door-status 关闭(默认) |
door-status 开启 |
|---|---|---|
门禁 + accessStatus: 1 |
on/ico_mj.png(常规图标) |
access/open_door.png |
门禁 + accessStatus: 0 |
on/ico_mj.png |
access/close_door.png |
门禁但不带 accessStatus |
常规图标 | 常规图标(自动回退) |
| 摄像机等其它设备 | 不受影响 | 不受影响 |
显式传了 icon |
用 icon |
用 icon(显式最高优先) |
图标资源在插件 static/icons/gis/access/(与 web 端 assets/images/resource/access/ 同源)。与 web 端一致:开启后按 accessStatus 优先选图,即离线/故障的门禁也显示开门/关门状态。
气泡与交互
- 气泡由 DOM 渲染,带指向图标的小尖角;点位贴近屏幕上边时自动翻到点位下方,贴近左右边缘时整体收进屏幕内且尖角仍对准点位
- 点击点位默认自动平移到地图中心(
auto-center-marker="false"可关闭) - 点空白处收起气泡,同时抛出
map-click(hide-popup-on-map-tap="false"可保留气泡)
气泡多按钮(点位级操作入口)
在 popup.actions 配操作项,气泡底部渲染一排等宽按钮,点击抛 popup-action:
popup: {
title: '东门摄像机-01',
fields: [{ label: '在线状态', value: '在线' }],
actions: [
{ key: 'video', text: '实时视频' },
{ key: 'detail', text: '详情' },
],
}
<yolo-gis :markers="markers" @popup-action="onPopupAction" />
function onPopupAction({ marker, actionKey }) {
if (actionKey === 'video') uni.navigateTo({ url: '/pages/video/play?id=' + marker.id })
}
未配 actions 时行为不变(popup-action-text 单行提示 + 整泡 popup-click),两种用法可共存。
告警动图(超量自动降级)
type: 'alarm' 的点位用告警 GIF(static/icons/gis/alarm/anime_alart.gif)。同屏动图超过 10 个时自动降级为静态图 + CSS 红圈脉冲 —— 动图解码开销大,密集告警页容易卡顿;降级时控制台打一行 告警动图点位 N 个(>10),降级为静态图+CSS脉冲。阈值写在 dom-marker-layer.js(MAX_GIF_MARKERS)。
点位朝向旋转(摄像机)
markers 带 deviationAngle(监控朝向角)即自动旋转图标,按 22.5° 一档量化(与 web 端 angleArray 一致):
{ id: 'c1', lng: 117.0034, lat: 42.0031, deviceType: '01', ptzType: '01', deviationAngle: 100 }
标注类页面允许用户调角度时开 marker-rotatable:枪机图标会拆成「底座 + 字模」两层,旋转只作用于字模(蓝底徽标与底部针脚保持不动),并用 marker-rotate="{ id, deg }" 实时预览(不重画整层点位)。
选中高亮(列表 ↔ 地图联动)
<yolo-gis :markers="markers" :selected-id="selectedId" @marker-click="m => selectedId = m.id" />
蓝色描边环持久框住选中点位(与 focus-point 的瞬时脉冲互不冲突);只切 class、不重画点位,点位全量重画后自动恢复。按 id 或 deviceId 匹配。
点位拖动标注(取新坐标)
「设备地图标注」类页面:给 draggable-marker-id 指定当前要调整的点位,用户拖动图标跟手移动,松手抛 marker-dragend:
<yolo-gis :markers="markers" :draggable-marker-id="dragId" @marker-dragend="End" />
function End({ data, lng, lat }) {
// 由页面决定保存时机(可先存本地、点「保存」再提交接口)
}
GPS 定位与内置定位钮
<!-- 内置定位钮:点一下去我的位置、再点回预设中心 -->
<yolo-gis :map-vo="mapVo" :markers="markers" show-locate @location-error="onLocationError" />
<!-- 只要 GPS 能力 + 地图蓝点,按钮自己画 -->
<yolo-gis :map-vo="mapVo" :markers="markers" show-location ref="mapRef" />
const pos = await mapRef.value.locate() // { longitude, latitude, accuracy },失败返回 null 并抛 location-error
- 定位成功后地图落下「我的位置」蓝点(内联 SVG,无图片依赖),并抛
location-change tools-direction/tools-top/tools-right调工具组排列与位置;tools-style可把它挂到跟手面板上(如{ right:'24rpx', bottom:'52px', opacity:1 })- App 端需定位权限;H5 端受浏览器权限与 HTTPS 限制,定位失败会抛
location-error(页面提示用户即可)
六、场景与工具
场景预设 + 单项覆盖
import { SCENE_PRESETS, sceneProps } from '@/uni_modules/yolo-gis/js_sdk/map-scene.js'
SCENE_PRESETS.device // 设备地图:fitMarkers + 状态筛选 + 气泡
SCENE_PRESETS.deviceManage // 设备标注:manageMode,无气泡(详情走页面弹窗)
SCENE_PRESETS.alarm // 告警地图:告警动图点位 + 点击居中
SCENE_PRESETS.dense // 点位密集:cluster(50px)
sceneProps('dense', { showPopup: false }) // 预设 + 覆盖,返回可直接 v-bind 的对象
| 业务场景(对应 web 端) | 关键参数 | 说明 |
|---|---|---|
| 楼层设备地图 / 资源可视化 | door-status、show-badge、fit-markers |
门禁开关门、设备等级角标 |
| 设备地图标注 | manage-mode、draggable-marker-id、marker-rotatable、popup.actions |
图标不分在线离线;拖动取新坐标、摄像机朝向滑杆、气泡「移动」按钮 |
| 告警地图 / 报警联动 | focus-point、auto-center-marker |
推送后 focusPoint = { id } 定位并高亮 |
| 点位密集页 | cluster + cluster-pixels |
聚合数字气泡,点击放大 |
| 只想自己控制显示 | show-popup=false + 自己组装 markers[].popup |
气泡字段全自定义 |
web 端参数 → 移动端属性对照
宿主项目与 web 端是同一套业务时按此表平移;纯移动端项目可忽略。
| web 端(gisfactory / basegis) | 移动端(YoloGis) |
|---|---|
popupConfig.iconResolver(门禁开关门) |
door-status |
popupConfig.showLevelBadge |
show-badge |
gisCommon.isGisManage(管理模式) |
manage-mode |
popupConfig.component(Vue 弹窗) |
marker-click + 页面 DetailPopup(移动端统一走页面弹窗) |
popupConfig.title/width/height |
markers[].popup = { title, fields } 自定义 |
basegis.pointerSymbol(icon, 0, 28, 38, …) |
默认 28×38,marker-scale 缩放 |
clusterByPixelDistance(points, map, 50) |
cluster + cluster-pixels=50 |
flyTo(lng, lat) / flashMarkerByDeviceId(id) |
focus-point |
switchMapShow / regionMode |
楼层用 DropdownFilter 的 mode:'tree'(页面侧,见示例页) |
baseToolbarShow / 绘制工具 / 热力图 |
⏳ 规划中(见文末「后续批次」) |
可运行的完整示例:pages/demo/map/GisMapScene.vue(编排层 + 四种场景一键切换)、pages/demo/map/GisMap.vue(只用组件的最小用法)、pages/demo/map/GisLocation.vue(GPS 定位 + 内置定位钮)。
上面几个示例页位于作者宿主项目内,插件包中不含;按本文件第一、二节的写法即可自行复现。
js_sdk 工具一览
| 模块 | 能力 | 对应 web 端 |
|---|---|---|
marker-style.js |
resolveMarkerSymbol(m, { doorStatus }) / resolveStatus(在线绿 / 离线灰 / 故障红 / 告警亮红)/ resolveAccessDoorIcon / cameraRotation(朝向角 22.5° 量化)/ DEVICE_TYPE_NAMES / resolveBadge |
symbolStyle.js / getCameraStatusMarker |
my-location.js |
getMyLocation(GPS 取点)/ myLocationMarkerOf(生成「我的位置」点位)/ LOCATION_ICON |
web 端 getLocation 类能力 |
map-service.js |
getMapVoList / getMapVoByFloorCode / getDefaultMapVo / groupByBuilding |
basegis.showMap/changeFloor 的数据处理 |
map-env.js |
loadMaptalks / getMaptalks / pinContainerSize / watchContainerSize / resolveIconUrl / probeTile |
— |
dom-marker-layer.js |
createDomMarkerLayer({...}) → mount/render/update/schedule/hidePopup/centerOn/focus/setSelected/unmount;含选中描边、气泡多按钮、告警动图降级 |
Leaflet marker 思路 |
marker-adapter.js |
normalizeDevice / toDeviceMarkers / toAlarmMarkers / devicePopupFields / summarizeMarkers |
basegis.addXxxMarkers + getInfoWin 的字段部分 |
map-scene.js |
useGisScene / sceneProps / SCENE_PRESETS / buildFloorTree / STATUS_OPTIONS |
basegis 的建图与楼层切换流程 |
gis-utils.js |
lngLatToTile / buildTileUrl / probeTileUrl / haversineDistance / fmtLngLat / clampZoom / fmtDistance |
散落各处 |
七、使用须知(踩坑)
- prop 名是
mapVo(不是mapVO):模板:map-vo经 kebab→camelCase 转换后是mapVo,声明成mapVO将永远收不到值。 - 通信走单个
:prop(载荷 JSON 字符串):实测同节点绑多个自定义 prop 时 renderjs 的 change observer 可能不触发,勿改回多 prop。 - H5 端切片跨域:
mapServiceUrl与前端不同源时浏览器按 CORS 拦截切片,需切片服务 nginx 加Access-Control-Allow-Origin,或开发期走 devServer 代理;App 端 webview 无跨域限制。 - 容器必须有确定高度:页面里给地图容器一个显式高度(如
height: 640rpx);组件建图前会把容器width/height钉成整数 CSS px(640rpx ≈ 322.56px这类小数会让 canvas 尺寸抖动,maptalks 反复 resize 触发重绘链路异常)。 - 鸿蒙端点位用 DOM 渲染:canvas 矢量层在鸿蒙 ArkWeb 上静止态合成不可靠(详见「九、已弃用」),本项目点位/气泡统一 DOM;点位数建议数百以内。
八、排障
控制台日志统一带 [YoloGis] 前缀,按下面的顺序看:
| 日志 | 含义 / 下一步 |
|---|---|
env: {webgl, imageBitMap, dpr, touch} |
环境能力自检(建图时打印) |
map created, container: 378x323 center: … zoom: … |
建图成功,容器尺寸与初始视野;尺寸为 0 说明容器没高度(见须知 4) |
切片可达: http://…/19/432543/194619.png |
切片连通性自检通过;没有这行说明切片地址或跨域有问题 |
图标加载失败: url |
图标路径不对(icon 字段或插件 static 资源) |
DOM 点位已渲染: N 个 |
点位层已上屏;N 为 0 检查 markers 是否为空 / 坐标是否缺失 |
告警动图点位 N 个(>10),降级为静态图+CSS脉冲 |
同屏告警点过多已自动降级省性能(正常提示,非错误) |
定位钮点击 → 去我的位置 / 回预设中心 |
内置定位钮的点击分支(排障时确认点击有被识别) |
定位失败: 错误对象 |
GPS 取点失败(权限/信号),页面会在 location-error 里收到,提示用户即可 |
捕获 Position is NaN,调用栈:… |
鸿蒙 webview 上的定位异常(已内置交互期点击防御),有栈就能精确定位 |
九、已弃用:canvas 矢量层渲染点位
早期版本用 maptalks VectorLayer(canvas)画图标点位,已彻底移除,勿再使用。
原因(真机实测,详见 changelog 踩坑 7、8):maptalks 画布渲染器把所有图层 canvas 合成到地图主 canvas 上显示,点位层走「异步加载图标 → 帧外补画 → 标脏 → 合成」链路,在鸿蒙 ArkWeb 上静止态合成不可靠 —— 层里已经画好(实测 6 万多像素)、屏幕却是空的,一拖动(交互帧每帧直接合成)才出现;底图瓦片层没有这个问题。配套的强制合成、自愈重建、资源预加载等兜底均无法根治。
现方案:点位(图标/圆点)与气泡统一用 DOM 元素渲染,坐标仍由 maptalks 换算(coordinateToContainerPoint),随地图事件按 rAF 合并刷新 —— 与 Leaflet marker 同思路,从根上绕开这一类 canvas 问题;底图 / 缩放 / 投影 / 事件体系仍由 maptalks 提供。
十、目录结构
yolo-gis/
├─ static/
│ ├─ maptalks.min.js # maptalks 1.6.1 UMD 构建(官方原样,script 注入加载)
│ ├─ maptalks.css # maptalks 官方样式(控件/气泡/面板)
│ └─ icons/gis/ # on/off/fail 三态设备切图 + glyph 字模(朝向旋转用)
│ # + alarm 告警动图 + access 门禁开关门
├─ js_sdk/ # 内部能力层(纯 JS,可被组件与页面复用)
│ ├─ map-env.js # maptalks 加载、容器尺寸稳定、图标地址解析、切片自检
│ ├─ dom-marker-layer.js # DOM 点位层:点位/角标/聚合/聚焦/选中/拖动/气泡/动图降级
│ ├─ marker-style.js # 点位样式工厂:设备图标、状态判定与配色、门禁开关门、等级角标、朝向量化
│ ├─ marker-adapter.js # 业务数据 → markers:字段归一化 + 气泡摘要字段
│ ├─ map-scene.js # 场景编排:useGisScene 流程 + SCENE_PRESETS 场景预设
│ ├─ map-service.js # 楼层地图配置加工(与 web 端同源)
│ ├─ my-location.js # GPS 定位取点 + 「我的位置」点位生成
│ └─ gis-utils.js # 坐标工具(瓦片号/距离/格式化等)
└─ components/
└─ yolo-gis/yolo-gis.vue # 唯一组件入口 YoloGis(<yolo-gis>):props/emits + renderjs 地图生命周期
附:第三方代码声明
插件内 static/maptalks.min.js 为 maptalks 官方发布文件的原样分发(未做任何修改),请在使用与分发时保留其文件内的版权与协议头:
- maptalks v1.6.1 — LICENSE: BSD-3-Clause,(c) 2016-2025 maptalks.org(https://github.com/maptalks/maptalks.js)
- 该文件内另含 mapbox feature-filter 片段,文件内声明为:
(c) mapbox 2016 and maptalks 2018 — License: MIT, header required
本插件自身不采集任何用户数据;地图切片请求由使用者自行配置的 mapVo.mapServiceUrl 发出。
十一、后续批次(规划中)
- 绘制工具:drawRectangle / drawPolygon / drawCircle / drawLine / drawPoint + 清除(对应 web 端 BaseToolbar,区域/围栏类页面用)
- 热力图:createHeatMap / updateHeatMap / destroyHeatMap(需引入 maptalks.heatmap 插件文件,「风险热力图」页依赖)
- 点位文字标注:区域/楼栋名称跟随图标(与设备点位分开的标注体系,含增删改查)

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 15
赞赏 1
下载 12657873
赞赏 1955
赞赏
京公网安备:11010802035340号