arcgis.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. <template>
  2. <div class="arcgis">
  3. <div id="viewDiv"></div>
  4. <div id="marker">
  5. <div v-for="(marker, index) of markers" :key="index" v-show="marker.show"
  6. :id="'arcgic-marker-' + marker.slot" class="arcgis-marker" :style="'left: '+marker.x+'px; top: '+marker.y+'px;'">
  7. <slot :name="marker.slot"></slot>
  8. </div>
  9. </div>
  10. </div>
  11. </template>
  12. <script>
  13. import Map from "@arcgis/core/Map";
  14. import Basemap from "@arcgis/core/Basemap";
  15. import Graphic from "@arcgis/core/Graphic";
  16. import SpatialReference from "@arcgis/core/geometry/SpatialReference";
  17. import MapView from "@arcgis/core/views/MapView";
  18. import SceneView from "@arcgis/core/views/SceneView";
  19. import MapImageLayer from "@arcgis/core/layers/MapImageLayer";
  20. import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
  21. import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol";
  22. import "@arcgis/core/assets/esri/themes/light/main.css";
  23. const mapUrl = "http://61.161.152.110:12345/arcgis/rest/services/NX_MAP_15/MapServer"; // ArcMap地址
  24. // const mapUrl = "http://172.16.6.30:12345/arcgis/rest/services/NX_MAP_15/MapServer"; // ArcMap地址
  25. let basemap = null;
  26. let map = null;
  27. let view = null;
  28. let point_graphicsLayer = null;
  29. let line_graphicsLayer = null;
  30. let text_graphicsLayer = null;
  31. let img_graphicsLayer = null;
  32. let html_graphicsLayer = null;
  33. let point_graphics = [];
  34. let line_graphics = [];
  35. let text_graphics = [];
  36. let img_graphics = [];
  37. let html_graphics = [];
  38. export default {
  39. // 名称
  40. name: "arcgis",
  41. // 使用组件
  42. components: {},
  43. // 传入参数
  44. props: {
  45. data: {
  46. type: Object,
  47. default: () => {
  48. return {
  49. mode: "2D", // 模式 2D 3D
  50. title: "宁夏地图", // 标题
  51. center: [106.230909, 38.487193], // 初始中心点
  52. height: 654, // 3D地图初始相机高度
  53. tilt: 65, // 俯视角
  54. scale: 128000, // 缩放
  55. }
  56. },
  57. }
  58. },
  59. // 自定义事件
  60. emits: {
  61. when: null, // 地图加载完成
  62. clickMap: null, // 点击地图(可点击元素)
  63. },
  64. // 数据
  65. data() {
  66. return {
  67. fanStateImgMapping: [{
  68. name: "待机",
  69. code: "dj",
  70. img: require("@assets/map/fan/green.png")
  71. },
  72. {
  73. name: "运行",
  74. code: "yx",
  75. img: require("@assets/map/fan/blue.png")
  76. },
  77. {
  78. name: "限电",
  79. code: "xd",
  80. img: require("@assets/map/fan/purple.png")
  81. },
  82. {
  83. name: "故障",
  84. code: "gz",
  85. img: require("@assets/map/fan/red.png")
  86. },
  87. {
  88. name: "检查",
  89. code: "jc",
  90. img: require("@assets/map/fan/orange.png")
  91. },
  92. {
  93. name: "离线",
  94. code: "lx",
  95. img: require("@assets/map/fan/black.png")
  96. },
  97. {
  98. name: "受累",
  99. code: "sl",
  100. img: require("@assets/map/fan/white.png")
  101. },
  102. ],
  103. syzImg: require("@assets/temp.png"),
  104. markers: [],
  105. }
  106. },
  107. // 函数
  108. methods: {
  109. // 初始化地图
  110. initMap: function() {
  111. basemap = new Basemap({
  112. // 底图
  113. baseLayers: [
  114. new MapImageLayer({
  115. url: mapUrl,
  116. title: this.data.title,
  117. spatialReference: SpatialReference.WGS84,
  118. }),
  119. ],
  120. title: this.data.title,
  121. spatialReference: SpatialReference.WGS84,
  122. });
  123. map = new Map({
  124. // 地图容器
  125. basemap: basemap,
  126. });
  127. if (this.data.mode == "3D") {
  128. view = new SceneView({
  129. // 3D显示图层
  130. map: map,
  131. center: this.data.center,
  132. camera: {
  133. position: {
  134. x: this.data.center[0], // lon
  135. y: this.data.center[1], // lat
  136. z: this.data.height, // elevation in meters
  137. },
  138. tilt: this.data.tilt,
  139. },
  140. container: this.$el.querySelector("#viewDiv"),
  141. });
  142. } else {
  143. view = new MapView({
  144. // 3D显示图层
  145. map: map,
  146. center: this.data.center,
  147. container: this.$el.querySelector("#viewDiv"),
  148. });
  149. }
  150. view.scale = this.data.scale;
  151. //去掉版权
  152. view.ui._removeComponents(["attribution"]);
  153. view.when(() => {
  154. this.when();
  155. this.$emit('when');
  156. });
  157. },
  158. when: function() {
  159. // 当地图加载完成
  160. point_graphicsLayer = new GraphicsLayer({
  161. graphics: []
  162. });
  163. line_graphicsLayer = new GraphicsLayer({
  164. graphics: []
  165. });
  166. text_graphicsLayer = new GraphicsLayer({
  167. graphics: []
  168. });
  169. img_graphicsLayer = new GraphicsLayer({
  170. graphics: []
  171. });
  172. html_graphicsLayer = new GraphicsLayer({
  173. graphics: []
  174. });
  175. map.add(line_graphicsLayer);
  176. map.add(point_graphicsLayer);
  177. map.add(text_graphicsLayer);
  178. map.add(img_graphicsLayer);
  179. map.add(html_graphicsLayer);
  180. view.on("click", (event) => {
  181. view.hitTest(event).then((response) => {
  182. let result = null;
  183. if (response.results.length) {
  184. const canClick = ["picture-marker", "text"];
  185. response.results.forEach(item => {
  186. if (canClick.indexOf(item.graphic.symbol.type) >= 0) {
  187. result = item.graphic.attributes;
  188. }
  189. })
  190. }
  191. if (result != null) {
  192. this.$emit('clickMap', result);
  193. }
  194. })
  195. });
  196. view.watch("extent", (evt) => {
  197. this.markers.forEach((marker, index) => {
  198. let graphics = html_graphics[index];
  199. let screenPoint = view.toScreen(graphics.geometry);
  200. marker.x = screenPoint.x - marker.ox;
  201. marker.y = screenPoint.y - marker.oy;
  202. if (evt.height < 0.045) {
  203. if (!marker.show) {
  204. marker.show = true;
  205. graphics.symbol = new SimpleMarkerSymbol({
  206. color: "transparent",
  207. outline: {
  208. color: [255, 255, 255],
  209. width: 0
  210. }
  211. });
  212. }
  213. } else {
  214. if (marker.show) {
  215. marker.show = false;
  216. graphics.symbol = new SimpleMarkerSymbol({
  217. color: [5,187,76,0.75],
  218. outline: {
  219. color: [5,187,76],
  220. width: 2
  221. }
  222. });
  223. }
  224. }
  225. });
  226. });
  227. },
  228. // 通过name或code获取img
  229. getFanImg: function(nameOrState) {
  230. const item = this.fanStateImgMapping.find(t => t.name == nameOrState || t.code ==
  231. nameOrState);
  232. if (item) {
  233. return item.img;
  234. } else {
  235. console.error(nameOrState, "对应的图片不存在");
  236. return "";
  237. }
  238. },
  239. // 添加html
  240. addHtmlPoint: function (point, slot, ox=0, oy=0) {
  241. let item = {
  242. geometry: {
  243. type: "point",
  244. spatialReference: SpatialReference.WGS84,
  245. x: point[0],
  246. y: point[1],
  247. },
  248. symbol: {
  249. type: "simple-marker",
  250. color: "transparent",
  251. outline: {
  252. color: [255, 255, 255],
  253. width: 0
  254. }
  255. },
  256. // symbol: null,
  257. attributes: {},
  258. popupTemplate: null
  259. };
  260. let graphic = new Graphic(item);
  261. html_graphics.push(graphic);
  262. html_graphicsLayer.add(graphic);
  263. let screenPoint = view.toScreen(graphic.geometry);
  264. let marker = {
  265. slot: slot,
  266. ox: ox,
  267. oy: oy,
  268. x: screenPoint.x - ox,
  269. y: screenPoint.y - oy,
  270. show: true,
  271. };
  272. this.markers.push(marker);
  273. return marker;
  274. },
  275. // 添加图片点
  276. addImagePoint: function (point, src, width, height) {
  277. let item = {
  278. geometry: {
  279. type: "point",
  280. spatialReference: SpatialReference.WGS84,
  281. x: point[0],
  282. y: point[1]
  283. },
  284. symbol: {
  285. type: "picture-marker",
  286. url: this.tempImg,
  287. width: width,
  288. height: height,
  289. xoffset: 0,
  290. yoffset: 0
  291. },
  292. attributes: {},
  293. popupTemplate: null
  294. };
  295. console.log(item)
  296. let graphic = new Graphic(item);
  297. img_graphics.push(graphic);
  298. img_graphicsLayer.add(graphic);
  299. },
  300. // 移除
  301. remove: function (type, obj) {
  302. if (type == "html") {
  303. let markerIndex = this.markers.findIndex(t => t.slot == obj.slot);
  304. // let marker = this.markers[markerIndex];
  305. this.markers.splice(markerIndex, 1);
  306. let graphic = html_graphics[markerIndex];
  307. html_graphics.splice(markerIndex, 1);
  308. html_graphicsLayer.remove(graphic);
  309. } else {
  310. console.info("arcgis: No type:", type)
  311. }
  312. },
  313. // 添加图片点
  314. addImgPoint: function(jsonItem) {
  315. let item = JSON.parse(JSON.stringify(jsonItem));
  316. item.geometry.type = "point";
  317. item.geometry.spatialReference = SpatialReference.WGS84;
  318. item.symbol = {
  319. type: "picture-marker",
  320. url: item.attributes.type == "升压站" ? this.syzImg : this.getFanImg(item.attributes.state),
  321. width: item.attributes.type == "升压站" ? "96px" : "48px",
  322. height: item.attributes.type == "升压站" ? "96px" : "48px",
  323. xoffset: 0,
  324. yoffset: 18
  325. };
  326. let graphic = new Graphic(item);
  327. point_graphics.push(graphic);
  328. point_graphicsLayer.add(graphic);
  329. this.addImgText(jsonItem);
  330. },
  331. // 添加图片文字
  332. addImgText: function(jsonItem) {
  333. let item = JSON.parse(JSON.stringify(jsonItem));
  334. item.geometry.type = "point";
  335. item.geometry.spatialReference = SpatialReference.WGS84;
  336. item.symbol = {
  337. type: "text",
  338. color: "white",
  339. haloColor: "black",
  340. haloSize: "1px",
  341. text: item.attributes.code,
  342. xoffset: 0,
  343. yoffset: -10,
  344. font: {
  345. size: 12,
  346. // family: "Josefin Slab",/
  347. weight: "bold"
  348. }
  349. };
  350. let graphic = new Graphic(item);
  351. text_graphics.push(graphic);
  352. text_graphicsLayer.add(graphic);
  353. },
  354. // 添加线段
  355. addLine: function(jsonItem) {
  356. let item = JSON.parse(JSON.stringify(jsonItem));
  357. item.geometry.type = "polyline";
  358. item.geometry.spatialReference = SpatialReference.WGS84;
  359. item.symbol = {
  360. type: "simple-line",
  361. color: "#05bb4c",
  362. width: item.attributes.width
  363. }
  364. let graphic = new Graphic(item);
  365. line_graphics.push(graphic);
  366. line_graphicsLayer.add(graphic);
  367. },
  368. addFanByJson: function(jsonObj, lineJsonObj) {
  369. jsonObj.forEach(item => {
  370. this.addImgPoint(item);
  371. });
  372. lineJsonObj.forEach(item => {
  373. this.addLine(item);
  374. });
  375. },
  376. goto: function(point) {
  377. view.goTo({
  378. center: point
  379. }).catch(function(error) {
  380. if (error.name != "AbortError") {
  381. console.error(error);
  382. }
  383. });
  384. }
  385. },
  386. // 生命周期钩子
  387. beforeCreate() {
  388. // 创建前
  389. },
  390. created() {
  391. // 创建后
  392. },
  393. beforeMount() {
  394. // 渲染前
  395. },
  396. mounted() {
  397. // 渲染后
  398. this.initMap();
  399. },
  400. beforeUpdate() {
  401. // 数据更新前
  402. },
  403. updated() {
  404. // 数据更新后
  405. },
  406. }
  407. </script>
  408. <style lang="less">
  409. .arcgis {
  410. width: 100%;
  411. height: 100%;
  412. position: relative;
  413. overflow: hidden;
  414. #viewDiv {
  415. position: absolute;
  416. z-index: 1;
  417. width: 100%;
  418. height: 100%;
  419. top: 0;
  420. left: 0;
  421. }
  422. #marker {
  423. position: absolute;
  424. z-index: 2;
  425. width: 0;
  426. height: 0;
  427. top: 0;
  428. left: 0;
  429. }
  430. .arcgis-marker {
  431. position: absolute;
  432. z-index: 2;
  433. }
  434. }
  435. </style>