getStart.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <!-- 画板 -->
  2. <template>
  3. <div ref="baseMap" class="base-map">
  4. <canvas
  5. id="floorMap"
  6. :width="canvasWidth"
  7. :height="canvasHeight"
  8. tabindex="0"
  9. ></canvas>
  10. </div>
  11. </template>
  12. <script>
  13. import { SGraphScene } from "@persagy-web/graph/lib";
  14. import { SGraphView, SGraphSvgItem } from "@persagy-web/graph";
  15. import { SFloorParser, getJsonz } from "@persagy-web/big/lib";
  16. import { SZoneParser } from "@persagy-web/big";
  17. export default {
  18. props: {
  19. // 是否展示大小控制器
  20. hasShowContro: {
  21. type: Boolean,
  22. default: true,
  23. required: false,
  24. },
  25. // //// 关于底图
  26. // 一,展示底图的元素
  27. // 3.是否展示柱子
  28. isShowColumn: {
  29. type: Boolean,
  30. default: false,
  31. required: false,
  32. },
  33. // 4.是否展示墙
  34. isShowWall: {
  35. type: Boolean,
  36. default: false,
  37. required: false,
  38. },
  39. // 5.是否展示虚拟墙
  40. isShowVirtualWall: {
  41. type: Boolean,
  42. default: false,
  43. required: false,
  44. },
  45. // 6.是否展示门
  46. isShowDoor: {
  47. type: Boolean,
  48. default: false,
  49. required: false,
  50. },
  51. // 7.是否展窗户
  52. isShowWindow: {
  53. type: Boolean,
  54. default: false,
  55. required: false,
  56. },
  57. // 8.是否显示空间
  58. isSpaceSelectable: {
  59. type: Boolean,
  60. default: true,
  61. required: false,
  62. },
  63. // 是否展示底图名称
  64. showBaseName: {
  65. type: Boolean,
  66. default: false,
  67. required: false,
  68. },
  69. },
  70. data() {
  71. return {
  72. canvasWidth: 0, // 画布的宽
  73. canvasHeight: 0, // 画布的高
  74. view: null, // 视图 view
  75. scene: null, // 场景类
  76. };
  77. },
  78. methods: {
  79. // 初始化
  80. init() {
  81. this.clearImg();
  82. this.view ? (this.view.scene = this.scene) : null;
  83. // 获取压缩包数据并解压
  84. this.getMapBlob();
  85. },
  86. // 选中图例
  87. emitChoice(itemList) {
  88. this.$emit("emitChoice", itemList);
  89. this.choiceListLength = itemList.length;
  90. },
  91. // 鼠标点击画板事件
  92. vueOnMouseDown(e) {
  93. // 如果为非拖动操作方可执行点击事件
  94. if (!this.view.isDrag) {
  95. this.$emit("vueOnMouseDown", e);
  96. // 是否需要打点(必须在空间内)
  97. // setTimeout 用于让选中事件先于vue 点击
  98. setTimeout(() => {
  99. if (this.choiceListLength) {
  100. if (
  101. (typeof this.SetNewMarkConfig == "boolean" &&
  102. this.SetNewMarkConfig == true) ||
  103. typeof this.SetNewMarkConfig == "object"
  104. ) {
  105. this.setNewMark(e, this.SetNewMarkConfig);
  106. }
  107. }
  108. }, 100);
  109. }
  110. },
  111. // 请求获取地图的压缩包
  112. getMapBlob() {
  113. const url = this.mapUrl + this.dataKey;
  114. getJsonz(url).then((data) => {
  115. // 解析数据并放入压缩包中
  116. this.parserData(data);
  117. });
  118. },
  119. // 解析数据并注入 scene 类中
  120. parserData(data) {
  121. let parser = new SFloorParser();
  122. parser.parseData(data);
  123. parser.spaceList.forEach((t) => {
  124. //是否显示空间
  125. t.visible = this.isSpaceSelectable;
  126. //设置样式
  127. t.style = this.baseMapStyle;
  128. //是否展示名称
  129. t.showBaseName = this.showBaseName;
  130. // 是否可选
  131. t.selectable = true;
  132. t.connect("onMouseDown", this, this.clickSpaceItem);
  133. // 添加图例
  134. this.scene.addItem(t);
  135. });
  136. parser.wallList.forEach((t) => {
  137. //是否显示
  138. t.visible = this.isShowWall;
  139. // 是否可选
  140. t.selectable = true;
  141. this.scene.addItem(t);
  142. });
  143. parser.virtualWallList.forEach((t) => {
  144. //是否显示
  145. t.visible = this.isShowVirtualWall;
  146. // 是否可选
  147. t.selectable = true;
  148. this.scene.addItem(t);
  149. });
  150. parser.doorList.forEach((t) => {
  151. //是否显示
  152. t.visible = this.isShowDoor;
  153. // 是否可选
  154. t.selectable = true;
  155. this.scene.addItem(t);
  156. });
  157. parser.columnList.forEach((t) => {
  158. //是否显示
  159. t.visible = this.isShowColumn;
  160. // 是否可选
  161. t.selectable = true;
  162. this.scene.addItem(t);
  163. });
  164. parser.casementList.forEach((t) => {
  165. //是否显示
  166. t.visible = this.isShowWindow;
  167. // 是否可选
  168. t.selectable = true;
  169. this.scene.addItem(t);
  170. });
  171. // 画板是否可拖动
  172. this.view.DragMove = true;
  173. this.view.fitSceneToView();
  174. },
  175. // 图片缩小
  176. changeSize(isbiger) {
  177. if (isbiger) {
  178. this.view.scaleByPoint(
  179. (this.view.scale * 1.1) / this.view.scale,
  180. this.canvasWidth / 2,
  181. this.canvasHeight / 2
  182. );
  183. } else {
  184. this.view.scaleByPoint(
  185. (this.view.scale * 0.9) / this.view.scale,
  186. this.canvasWidth / 2,
  187. this.canvasHeight / 2
  188. );
  189. }
  190. },
  191. // 鼠标移入
  192. mouseEnter(item, e) {
  193. if (item.data.ElementType == "Mark") {
  194. item.status = "highlight";
  195. }
  196. this.$emit("mouseEnter", item, e);
  197. },
  198. // 鼠标移出
  199. mouseLeave(item, e) {
  200. if (item.data.ElementType == "Mark") {
  201. item.status = "default";
  202. }
  203. this.$emit("mouseLeave", e, item);
  204. },
  205. // 点击item
  206. clickSpaceItem(item, e) {
  207. console.log(item, e);
  208. this.$emit("clickSpaceItem", e, item);
  209. },
  210. // 点击item
  211. clickEquipItem(item, e) {
  212. this.$emit("clickEquipItem", e, item);
  213. },
  214. // 解析设备点
  215. mapEquipment(val) {
  216. this.scene ? this.scene.clearEquip() : "";
  217. const EqParse = new EquipmentParser(new EquipmentFactory());
  218. const markList = [];
  219. val.forEach((item) => {
  220. if (item.bimLocation) {
  221. const arr = item.bimLocation.split(",");
  222. const mark = {
  223. Id: item.equipId,
  224. ElementType: "Mark",
  225. equipId: item.equipId,
  226. Name: item.equipName,
  227. x: Number(arr[0]),
  228. y: Number(arr[1]),
  229. width: item.width,
  230. height: item.height,
  231. imgSource: item.imgSource,
  232. textObj: item.textObj ? item.textObj : null,
  233. tooltipMsg: item.tooltipMsg || [],
  234. };
  235. markList.push(mark);
  236. }
  237. });
  238. EqParse.parseData(markList);
  239. EqParse.markList.forEach((item) => {
  240. item.style = this.equipStyle;
  241. item.status = "disabled"; // 更具状态展示不同的效果;
  242. item.connect("mouseEnter", this, this.mouseEnter);
  243. item.connect("mouseLeave", this, this.mouseLeave);
  244. item.connect("click", this, this.clickEquipItem);
  245. this.scene.addItem(item);
  246. });
  247. this.scene.equipItemList = EqParse.markList;
  248. },
  249. // 解析业务空间
  250. mapSpace(val) {
  251. this.scene ? this.scene.clearSpace() : "";
  252. const parse = new SZoneParser();
  253. parse.parseData(val);
  254. parse.zoneList.forEach((item) => {
  255. item.connect("click", this, this.clickSpaceItem);
  256. this.scene.addItem(item);
  257. });
  258. this.scene.zoonItemList = parse.markList;
  259. },
  260. // 清空画布
  261. clearImg() {
  262. this.scene = new FloorScene();
  263. this.scene.emitChoice = this.emitChoice;
  264. this.scene.vueOnMouseDown = this.vueOnMouseDown;
  265. if (this.view) {
  266. this.view.update();
  267. }
  268. },
  269. // 打点操作
  270. setNewMark(e, markConfig) {
  271. let markWidth = 30;
  272. let markHeight = 30;
  273. // // 是否需要自定义mark
  274. if (typeof markConfig == "object") {
  275. markWidth = Number(markConfig.width) ? Number(markConfig.width) : 30;
  276. markHeight = Number(markConfig.height) ? Number(markConfig.height) : 30;
  277. }
  278. let mark = null;
  279. if (this.newMarkList.length) {
  280. mark = this.newMarkList[0];
  281. mark.x = e.x;
  282. mark.y = e.y;
  283. } else {
  284. // 有且只有一个mark
  285. const EqParse = new EquipmentParser(new EquipmentFactory());
  286. mark = {
  287. Id: new Date(),
  288. Name: "",
  289. width: markWidth,
  290. height: markHeight,
  291. x: e.x,
  292. y: e.y,
  293. };
  294. EqParse.parseData([mark]);
  295. EqParse.markList.forEach((item) => {
  296. item.style = this.equipStyle;
  297. this.scene.addItem(item);
  298. this.newMarkList.push(item);
  299. });
  300. }
  301. this.$emit("setNewMark", e);
  302. },
  303. },
  304. watch: {
  305. // 监听空间数组
  306. zoneList: {
  307. handler(val) {
  308. if (val && val.length) {
  309. this.mapSpace(val);
  310. }
  311. },
  312. deep: true,
  313. },
  314. // 监听设备数组
  315. equipmentList: {
  316. handler(val) {
  317. if (val && val.length) {
  318. this.mapEquipment(val);
  319. }
  320. },
  321. deep: true,
  322. },
  323. // 监听key
  324. dataKey: {
  325. handler(val) {
  326. if (val) {
  327. this.init();
  328. }
  329. },
  330. immediate: true,
  331. },
  332. },
  333. created() {
  334. this.clearImg();
  335. },
  336. mounted() {
  337. // 获取 canvas 的宽高
  338. this.canvasWidth = this.$refs.baseMap.offsetWidth;
  339. this.canvasHeight = this.$refs.baseMap.offsetHeight;
  340. // 初始化场景类
  341. this.view = new FloorView("floorMap");
  342. if (this.scene) {
  343. this.view.scene = this.scene;
  344. }
  345. },
  346. };
  347. </script>
  348. <style lang="less" scoped>
  349. .base-map {
  350. width: 100%;
  351. height: 100%;
  352. position: relative;
  353. .sacle-btn {
  354. position: absolute;
  355. right: 0;
  356. bottom: 0;
  357. }
  358. }
  359. </style>