更新记录

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.vue 590→466 行、注释 151→62 行;dom-marker-layer.js 448→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:设备等级/业务类型角标(deviceLevel 1→H红/2→Z橙/3→P绿,operationType 1→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 散落各处

七、使用须知(踩坑)

  1. prop 名是 mapVo(不是 mapVO):模板 :map-vo 经 kebab→camelCase 转换后是 mapVo,声明成 mapVO 将永远收不到值。
  2. 通信走单个 :prop(载荷 JSON 字符串):实测同节点绑多个自定义 prop 时 renderjs 的 change observer 可能不触发,勿改回多 prop。
  3. H5 端切片跨域:mapServiceUrl 与前端不同源时浏览器按 CORS 拦截切片,需切片服务 nginx 加 Access-Control-Allow-Origin,或开发期走 devServer 代理;App 端 webview 无跨域限制。
  4. 容器必须有确定高度:页面里给地图容器一个显式高度(如 height: 640rpx);组件建图前会把容器 width/height 钉成整数 CSS px(640rpx ≈ 322.56px 这类小数会让 canvas 尺寸抖动,maptalks 反复 resize 触发重绘链路异常)。
  5. 鸿蒙端点位用 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 插件文件,「风险热力图」页依赖)
  • 点位文字标注:区域/楼栋名称跟随图标(与设备点位分开的标注体系,含增删改查)

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

无

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议

暂无用户评论。