计算机系统应用教程网站

网站首页 > 技术文章 正文

vue + svg 构建地图系统心路历程

btikc 2024-09-06 18:13:17 技术文章 12 ℃ 0 评论


1.概述

家家职场(空间管理系统)是用来将职场的工位、会议室、功能房、物资等进行可视化的室内地图系统,并且员工可通过手机扫码或在地图上预定工位,员工信息自动关联到地图上;可以实时的查看职场资源的使用情况、物资的健康状况,通过报表系统可以明显的看出职场的资源使用率、BU的分布架构及人员变化,提高职场资源管理效率。


2.功能模块

2.1 地图编辑模块

2.2 工位资源逐级分配功能模块

2.3 全员资源可视化检索功能模块

2.4 权限管理模块 (本文不展开讨论)

2.5 资产管理平台/报表平台(本文不展开讨论)


3.效果展示

3.1

地图编辑功能展示

3.2

工位资源逐级分配模块功能展示

3.3

全员资源可视化检索功能


4.技术选型

4.1

外采 vs 自研

在外采与自研的选择上,从与现有系统融合、后期维护与扩展开发、成本等几个方面综合考虑,选择了自研。

4.2

svg vs canvas

在图形的绘制上 svg 与 canvas 两种方式都可以实现相关功能,经以下对比,选择SVG作为绘图工具。

4.3

vue vs react

vue和react都是出色的js开发框架,在这两者的选择上,更依赖于上面选择的SVG技术 ,xml类型的dom结构,配合vue的template风格来操作非常方便;项目前期的demo制作时,并不希望构建庞大的前端系统,一个html+vue可以实现大多数的前端功能,后期构建项目时又可以重用代码,综上选择VUE作为JS开发框架。


5.技术细节

5.1

定义物体坐标

四元数坐标(x,y,w,h),下面所有计算基于此定义:

x:物体左上角点的 x 坐标

y:物体左上角点的 y 坐标

w:物体横向宽度

h:物体纵向高度


5.2

定义坐标系统

最初设计系统时,最大的疑问就是,现实中的物体怎么生成到系统中,怎么做出对应关系,墙体、桌椅、其它物资怎么在系统中表达。

在这个问题的基础上就产生了底图(由楼层图生成,包含墙体,房间布局)、物体模型(如:桌椅、摄像头等物体的定义图形)、物体对象(把模型放置到地图中之后生成的物体)、自定义坐标系(物体的相对位置)等概念 ; 以画布的左上角为(0,0)原点坐标,将底图固定放置于画布中,以底图为基准放置物体,这样生成的图中物体、底图的坐标都是相对原点(0,0)的绝对位置,互相之间的位置也就确定了,生成的坐标就是自定义坐标系统数据。


5.3

定义地图对象

? 5.3.1 底图(将大厦 CAD 图精简为线条形式的简图,作为地图的位置参考系)

? 5.3.2 画布(地图渲染的容器,所有元素在容器中渲染)

? 5.3.3 大厦(底图及元素所在大厦)

? 5.3.4 楼层(底图及元素所在楼层)

? 5.3.5 楼层区域(A 区、B 区)

? 5.3.6 地图资源对象(放置在地图上的物体对象,类似于 java 中 new 出的对象)

? 5.3.7 资源模型 (生成地图中对象的模板,类似于 java 中的 class)

? 5.3.8 资源分类(工位、资产、物资、空间等,每个分类的物体有不同的"属性")

? 5.3.9 工具栏 (缩放 ,拖拽 ,单选 , 多选 , 框选 )

? 5.3.10 信息栏:资源配置信息展示及修改

? 5.3.11 权限系统(对接内部系统权限管理,根据权限展示不同的地图资源)


5.4

地图生成与显示—

地图编辑系统涉及的概念及计算方法

一个全新的系统上线,必须经历的一个过程是基础数据的生成,开发人员不了解工区的布局,比如:工位、消防栓、空调、喷淋等资产的位置和编号等信息,没有办法直接初始化数据,行政人员不了解技术知识,没有办法直接生成技术口径的数据 ; 而且工区的布局会不定时的变化,不能由技术直接操作数据,所以一个方便、简单易用的编辑功能成为整个系统的重点。下面介绍一下编辑功能开发过程中遇到的一些概念和计算方法。


? 5.4.1 碰撞检测

向地图上放置物体对象时,同类别的物体不能交叉放置,如:工位、冰箱、空调等 ; 而不同类别的物体可以交叉放置,如:工位上方可以放置摄像头、空调等,由于是 2D 效果图,显示出来的效果就是层叠放置。由此引出一个问题,怎样判断两个物体碰撞了。

在放置元素时,扫描所有页面对象,与当前要放置的元素对比,如果元素区域发生交集,判定为碰撞,即:已知两个元素 P1(x1,y1,w1,h1) P2(x2,y2,w2,h2),判断是否碰撞。

① x轴交叉条件:(x2>x1&&x2x2&&x1>x2+w2)

② y轴交叉条件: (y2>y1&&y2y2&&y1>y2+h2)

③ 【x轴交叉条件】与 【y轴交叉条件】同时满足时,为碰撞。


? 5.4.2 画面的缩放与拖拽

? 方案 1:transform: translate(0px, 0px) scale(1.5)

通过 scale 按比例缩放,再通过 translate 将画面移动到某个位置的方式来控制缩放和移动,这种方式有坐标系对应不上的问题,缩放后的坐标系需要换算,引起缩放不平滑或缩放跳跃,最终放弃了这种方式的控制。

? 方案 2(使用中):ViewBox(x, y, width, height)

① x,y 为需要显示的画面的左上角坐标,width,height定义矩形的尺寸

② 获取矩形的内容,扩大到画布尺寸,即完成了图像的放大操作

③ 控制x,y的位置,拖动画面

④ 控制w,h的大小,控制画布的缩放

系统中定义的坐标也是来源于 Viewbox 的控制方式。

? 5.4.3 物体的拖拽

JS 通用的拖拽控制方式,通过鼠标的按下,移动与抬起控制拖拽。

① Pstart(x1,y1):拖拽的起始位置

② Pend(x2,y2):鼠标的当前位置

③ mouseDown:开始拖拽 记录Pstart

④ mouseMove: 获取Pend 计算 Xp=x2-x1 Yp=y2-y1 ,并将结果赋值给元素

⑤ mouseUp:结束拖拽


? 5.4.4 物体的单选

在物体上添加 click 事件,被点击时记录为被选中即可完成单选操作。


? 5.4.5 物体的框选(多选)

已知鼠标按下与抬起的两点:start(x1,y1) end(x2,y2) 判断元素 P1(x,y,w,h)是否被框选,利用碰撞检测方案,将框选的区域看做一个物体(min(x1,x2),min(y1,y2),x1+x2,y1+y2),与它碰撞的物体都在框选范围内,标记为被选中,这种框选的方式来源于 windows 文件夹的操作方式。

? 5.4.6 物体的批量移动(键盘事件)

键盘事件发生时,判断上下左右键,分别“周期性的(300ms)”处理所有选中的元素 左(x--)右(x++)上(y++)下(y--) ,周期的大小选择会影响移动的顺滑程度。


? 5.4.7 物体的对齐问题(单排/双排批量放置)

在物体摆放时,工位的体量是最大的,而工位的布局又是整排摆放,如果一个一个工位去放置,工作量非常大,而且工位之间无法做到完美地对齐,基于上述问题,系统设计了一套可自定义数量,按单排、双排、横向排列、纵向排列的操作方式,大大减轻了地图部局的工作量。

? 5.4.8 自动避让弹窗

选中物体时,如果弹出明细信息把它遮挡,用户没办法知道自己点击的是哪个物体,所以需要使弹出的信息不遮挡目标物体。同样利用碰撞检测方案,将弹窗定义为一个物体,并从 HTML 坐标系映射到 SVG 坐标系,进行碰撞检测。

? 5.4.9 右键菜单分享位置的实现

右键菜单其实是一个简单的功能,屏蔽掉系统的右键菜单以后,自己在右键事件中制作一个菜单就可以完成,但是在右键菜单中分享 SVG 中的一个位置,就会出现一个 html 坐标系统中获取到的坐标与 SVG 中的坐标不一致的问题;SVG 中显示的图形可以放大、缩小、移动,从 HTML 坐标系中获取到的坐标并不能直接感知到这些操作,需要在获取到坐标以后,结合 SVG 图形的变换参数计算出最终要分享的坐标。


6.扩展

可扩展室内定位功能:

6.1

定位方式 wifi / 蓝牙

wifi:零成本,利用公司现有AP即可完成定位,精度不高;

蓝牙:有较低的成本,需要5米间隔部署低成本硬件,精度较高。

6.2

整合方案

APP/小程序 直接访问地图站点页面,将获取到的 rssi 信息参数传递给页面,由 js 执行定位,并将地图加载到定位的位置,增加图钉,完成实时位置的显示。

作者简介

牛俊福

C端及中台产研中心-效能平台部-信息系统团队

2014年加入汽车之家,现任职于C端及中台产研中心-效能平台部-信息系统团队,负责财务/行政类信息系统的研发工作,主要使用java、react、RN、vue等前后端技术。


作者:牛俊福

来源:微信公众号:之家技术

出处:https://mp.weixin.qq.com/s/VVWosXhD8FTiilv-aFJOUA

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表