|
@@ -0,0 +1,516 @@
|
|
|
+<template>
|
|
|
+ <div class="arcgis" :class="{'pointer': pointer}">
|
|
|
+ <div id="viewDiv"></div>
|
|
|
+ <teleport to=".esri-ui" v-if="teleport">
|
|
|
+ <div id="marker">
|
|
|
+ <div v-for="(marker, index) of markers" :key="index" v-show="marker.show"
|
|
|
+ :id="'arcgic-marker-' + marker.slot" class="arcgis-marker" :style="'left: '+marker.x+'px; top: '+marker.y+'px; transform: scale('+marker.scale+')'">
|
|
|
+ <slot :name="marker.slot"></slot>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </teleport>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import Map from "@arcgis/core/Map";
|
|
|
+ import Basemap from "@arcgis/core/Basemap";
|
|
|
+ import Graphic from "@arcgis/core/Graphic";
|
|
|
+ import SpatialReference from "@arcgis/core/geometry/SpatialReference";
|
|
|
+ import MapView from "@arcgis/core/views/MapView";
|
|
|
+ import SceneView from "@arcgis/core/views/SceneView";
|
|
|
+ import MapImageLayer from "@arcgis/core/layers/MapImageLayer";
|
|
|
+ import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
|
|
|
+ import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol";
|
|
|
+ import "@arcgis/core/assets/esri/themes/light/main.css";
|
|
|
+
|
|
|
+ const mapUrl = "http://10.155.32.4:9080/arcgis/rest/services/nxmap/MapServer"; // ArcMap地址
|
|
|
+ // const mapUrl = "http://10.155.32.4:9080/arcgis/rest/services/NX_MAP_15/MapServer"; // ArcMap地址
|
|
|
+ let basemap = null;
|
|
|
+ let map = null;
|
|
|
+ let view = null;
|
|
|
+ let point_graphicsLayer = null;
|
|
|
+ let line_graphicsLayer = null;
|
|
|
+ let text_graphicsLayer = null;
|
|
|
+ let img_graphicsLayer = null;
|
|
|
+ let html_graphicsLayer = null;
|
|
|
+ let point_graphics = [];
|
|
|
+ let line_graphics = [];
|
|
|
+ let text_graphics = [];
|
|
|
+ let img_graphics = [];
|
|
|
+ let html_graphics = [];
|
|
|
+
|
|
|
+ export default {
|
|
|
+ // 名称
|
|
|
+ name: "arcgis",
|
|
|
+ // 使用组件
|
|
|
+ components: {},
|
|
|
+ // 传入参数
|
|
|
+ props: {
|
|
|
+ data: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {
|
|
|
+ mode: "2D", // 模式 2D 3D
|
|
|
+ title: "宁夏地图", // 标题
|
|
|
+ center: [106.230909, 38.487193], // 初始中心点
|
|
|
+ height: 654, // 3D地图初始相机高度
|
|
|
+ tilt: 65, // 俯视角
|
|
|
+ scale: 128000, // 缩放
|
|
|
+ rotation: 0, // 正北顺时针旋转角度
|
|
|
+ ox: 0, // 标记整体偏移
|
|
|
+ oy: 0, // 标记整体偏移
|
|
|
+ }
|
|
|
+ },
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 自定义事件
|
|
|
+ emits: {
|
|
|
+ when: null, // 地图加载完成
|
|
|
+ clickMap: null, // 点击地图(可点击元素)
|
|
|
+ },
|
|
|
+ // 数据
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ fanStateImgMapping: [{
|
|
|
+ name: "待机",
|
|
|
+ code: "0",
|
|
|
+ img: require("@assets/map/fan/green.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "运行",
|
|
|
+ code: "1",
|
|
|
+ img: require("@assets/map/fan/blue.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "故障",
|
|
|
+ code: "2",
|
|
|
+ img: require("@assets/map/fan/red.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "离线",
|
|
|
+ code: "3",
|
|
|
+ img: require("@assets/map/fan/black.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "检修",
|
|
|
+ code: "4",
|
|
|
+ img: require("@assets/map/fan/orange.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "限电",
|
|
|
+ code: "5",
|
|
|
+ img: require("@assets/map/fan/purple.png")
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "限停",
|
|
|
+ code: "6",
|
|
|
+ img: require("@assets/map/fan/white.png")
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ syzImg: require("@assets/png/booster-station.png"),
|
|
|
+ markers: [],
|
|
|
+ pointer: false,
|
|
|
+ teleport: false, // 是否进行传送
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 函数
|
|
|
+ methods: {
|
|
|
+ // 世界转屏幕
|
|
|
+ worldToScreen: function (point) {
|
|
|
+ // var world = new Point(point.x, point.y, SpatialReference.WGS84);
|
|
|
+ // var screenPoint = map.toScreen(point);
|
|
|
+ },
|
|
|
+ // 屏幕转世界
|
|
|
+ screenToWorld: function (point) {},
|
|
|
+ // 偏移转经纬度
|
|
|
+ oToLL: function (x, y) {
|
|
|
+ return {
|
|
|
+ x: 0.00000899 * x,
|
|
|
+ y: 0.00001141 * y
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 初始化地图
|
|
|
+ initMap: function() {
|
|
|
+ basemap = new Basemap({
|
|
|
+ // 底图
|
|
|
+ baseLayers: [
|
|
|
+ new MapImageLayer({
|
|
|
+ url: mapUrl,
|
|
|
+ title: this.data.title,
|
|
|
+ spatialReference: SpatialReference.WGS84,
|
|
|
+ }),
|
|
|
+ ],
|
|
|
+ title: this.data.title,
|
|
|
+ spatialReference: SpatialReference.WGS84,
|
|
|
+ });
|
|
|
+ map = new Map({
|
|
|
+ // 地图容器
|
|
|
+ basemap: basemap,
|
|
|
+ });
|
|
|
+ if (this.data.mode == "3D") {
|
|
|
+ view = new SceneView({
|
|
|
+ // 3D显示图层
|
|
|
+ map: map,
|
|
|
+ center: this.data.center,
|
|
|
+ camera: {
|
|
|
+ position: {
|
|
|
+ x: this.data.center[0], // lon
|
|
|
+ y: this.data.center[1], // lat
|
|
|
+ z: this.data.height, // elevation in meters
|
|
|
+ },
|
|
|
+ tilt: this.data.tilt,
|
|
|
+ },
|
|
|
+ container: this.$el.querySelector("#viewDiv"),
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ view = new MapView({
|
|
|
+ // 2D显示图层
|
|
|
+ map: map,
|
|
|
+ center: this.data.center,
|
|
|
+ container: this.$el.querySelector("#viewDiv"),
|
|
|
+ rotation: this.data.rotation,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ view.scale = this.data.scale;
|
|
|
+ //去掉版权
|
|
|
+ view.ui._removeComponents(["attribution"]);
|
|
|
+ view.when(() => {
|
|
|
+ this.when();
|
|
|
+ this.$emit('when');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ when: function() {
|
|
|
+ // 当地图加载完成
|
|
|
+ this.teleport = true; // 传送
|
|
|
+ point_graphicsLayer = new GraphicsLayer({
|
|
|
+ graphics: []
|
|
|
+ });
|
|
|
+ line_graphicsLayer = new GraphicsLayer({
|
|
|
+ graphics: []
|
|
|
+ });
|
|
|
+ text_graphicsLayer = new GraphicsLayer({
|
|
|
+ graphics: []
|
|
|
+ });
|
|
|
+ img_graphicsLayer = new GraphicsLayer({
|
|
|
+ graphics: []
|
|
|
+ });
|
|
|
+ html_graphicsLayer = new GraphicsLayer({
|
|
|
+ graphics: []
|
|
|
+ });
|
|
|
+ map.add(line_graphicsLayer);
|
|
|
+ map.add(point_graphicsLayer);
|
|
|
+ map.add(text_graphicsLayer);
|
|
|
+ map.add(img_graphicsLayer);
|
|
|
+ map.add(html_graphicsLayer);
|
|
|
+ view.on("click", (event) => { // 监听鼠标点击 判断是否可以点击
|
|
|
+ view.hitTest(event).then((response) => {
|
|
|
+ let result = null;
|
|
|
+ if (response.results.length) {
|
|
|
+ const canClick = ["picture-marker", "text"];
|
|
|
+ response.results.forEach(item => {
|
|
|
+ if (canClick.indexOf(item.graphic.symbol.type) >= 0) {
|
|
|
+ result = item.graphic.attributes;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (result != null) {
|
|
|
+ this.$emit('clickMap', result);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ });
|
|
|
+ view.on("pointer-move", (event) => { // 监听鼠标移动 判断是否把鼠标变成小手
|
|
|
+ view.hitTest(event).then((response) => {
|
|
|
+ let result = null;
|
|
|
+ if (response.results.length) {
|
|
|
+ const canClick = ["picture-marker", "text"];
|
|
|
+ response.results.forEach(item => {
|
|
|
+ if (canClick.indexOf(item.graphic.symbol.type) >= 0) {
|
|
|
+ result = item.graphic.attributes;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (result) {
|
|
|
+ this.pointer= true;
|
|
|
+ } else {
|
|
|
+ this.pointer= false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ view.watch("extent", (evt) => {
|
|
|
+ this.markers.forEach((marker, index) => {
|
|
|
+ let graphics = html_graphics[index];
|
|
|
+ let screenPoint = view.toScreen(graphics.geometry);
|
|
|
+ marker.x = screenPoint.x - marker.ox;
|
|
|
+ marker.y = screenPoint.y - marker.oy;
|
|
|
+ if (marker.canScale) {
|
|
|
+ marker.scale = 0.0272 / evt.height;
|
|
|
+ // console.log(evt.height)
|
|
|
+ if (evt.height < 0.295) {
|
|
|
+ if (!marker.show) {
|
|
|
+ marker.show = true;
|
|
|
+ graphics.symbol = new SimpleMarkerSymbol({
|
|
|
+ color: "transparent",
|
|
|
+ outline: {
|
|
|
+ color: [255, 255, 255],
|
|
|
+ width: 0
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (marker.show) {
|
|
|
+ marker.show = false;
|
|
|
+ graphics.symbol = new SimpleMarkerSymbol({
|
|
|
+ color: [5,187,76,0.75],
|
|
|
+ outline: {
|
|
|
+ color: [5,187,76],
|
|
|
+ width: 2
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 通过name或code获取img
|
|
|
+ getFanImg: function(nameOrState) {
|
|
|
+ const item = this.fanStateImgMapping.find(t => t.name == nameOrState || t.code ==
|
|
|
+ nameOrState);
|
|
|
+ if (item) {
|
|
|
+ return item.img;
|
|
|
+ } else {
|
|
|
+ console.error(nameOrState, "对应的图片不存在");
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加html
|
|
|
+ addHtmlPoint: function (point, slot, ox=0, oy=0, scale=true) {
|
|
|
+ point[0] += this.oToLL(this.data.ox, this.data.oy).x;
|
|
|
+ point[1] += this.oToLL(this.data.ox, this.data.oy).y;
|
|
|
+ let item = {
|
|
|
+ geometry: {
|
|
|
+ type: "point",
|
|
|
+ spatialReference: SpatialReference.WGS84,
|
|
|
+ x: point[0],
|
|
|
+ y: point[1],
|
|
|
+ },
|
|
|
+ symbol: {
|
|
|
+ type: "simple-marker",
|
|
|
+ color: "transparent",
|
|
|
+ outline: {
|
|
|
+ color: [255, 255, 255],
|
|
|
+ width: 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // symbol: null,
|
|
|
+ attributes: {},
|
|
|
+ popupTemplate: null
|
|
|
+ };
|
|
|
+ let graphic = new Graphic(item);
|
|
|
+ html_graphics.push(graphic);
|
|
|
+ html_graphicsLayer.add(graphic);
|
|
|
+ let screenPoint = view.toScreen(graphic.geometry);
|
|
|
+ let marker = {
|
|
|
+ slot: slot,
|
|
|
+ ox: ox,
|
|
|
+ oy: oy,
|
|
|
+ x: screenPoint.x - ox,
|
|
|
+ y: screenPoint.y - oy,
|
|
|
+ scale: 1,
|
|
|
+ canScale: scale,
|
|
|
+ show: true,
|
|
|
+ };
|
|
|
+ this.markers.push(marker);
|
|
|
+ return marker;
|
|
|
+ },
|
|
|
+ // 添加图片点
|
|
|
+ addImagePoint: function (point, src, width, height) {
|
|
|
+ let item = {
|
|
|
+ geometry: {
|
|
|
+ type: "point",
|
|
|
+ spatialReference: SpatialReference.WGS84,
|
|
|
+ x: point[0],
|
|
|
+ y: point[1]
|
|
|
+ },
|
|
|
+ symbol: {
|
|
|
+ type: "picture-marker",
|
|
|
+ url: this.tempImg,
|
|
|
+ width: width,
|
|
|
+ height: height,
|
|
|
+ xoffset: 0,
|
|
|
+ yoffset: 0
|
|
|
+ },
|
|
|
+ attributes: {},
|
|
|
+ popupTemplate: null
|
|
|
+ };
|
|
|
+ console.log(item)
|
|
|
+ let graphic = new Graphic(item);
|
|
|
+ img_graphics.push(graphic);
|
|
|
+ img_graphicsLayer.add(graphic);
|
|
|
+ },
|
|
|
+ // 移除
|
|
|
+ remove: function (type, obj) {
|
|
|
+ if (type == "html") {
|
|
|
+ let markerIndex = this.markers.findIndex(t => t.slot == obj.slot);
|
|
|
+ // let marker = this.markers[markerIndex];
|
|
|
+ this.markers.splice(markerIndex, 1);
|
|
|
+ let graphic = html_graphics[markerIndex];
|
|
|
+ html_graphics.splice(markerIndex, 1);
|
|
|
+ html_graphicsLayer.remove(graphic);
|
|
|
+ } else {
|
|
|
+ console.info("arcgis: No type:", type)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加图片点
|
|
|
+ addImgPoint: function(jsonItem) {
|
|
|
+ let item = JSON.parse(JSON.stringify(jsonItem));
|
|
|
+ item.geometry.type = "point";
|
|
|
+ item.geometry.spatialReference = SpatialReference.WGS84;
|
|
|
+ item.geometry.x += this.oToLL(this.data.ox, this.data.oy).x;
|
|
|
+ item.geometry.y += this.oToLL(this.data.ox, this.data.oy).y;
|
|
|
+ item.symbol = {
|
|
|
+ type: "picture-marker",
|
|
|
+ url: item.attributes.type == "升压站" ? this.syzImg : this.getFanImg(item.attributes.state),
|
|
|
+ width: item.attributes.type == "升压站" ? "96px" : "48px",
|
|
|
+ height: item.attributes.type == "升压站" ? "96px" : "48px",
|
|
|
+ xoffset: 0,
|
|
|
+ yoffset: 18
|
|
|
+ };
|
|
|
+ let graphic = new Graphic(item);
|
|
|
+ point_graphics.push(graphic);
|
|
|
+ point_graphicsLayer.add(graphic);
|
|
|
+ this.addImgText(jsonItem);
|
|
|
+ },
|
|
|
+ // 添加图片文字
|
|
|
+ addImgText: function(jsonItem) {
|
|
|
+ let item = JSON.parse(JSON.stringify(jsonItem));
|
|
|
+ item.geometry.type = "point";
|
|
|
+ item.geometry.spatialReference = SpatialReference.WGS84;
|
|
|
+ item.geometry.x += this.oToLL(this.data.ox, this.data.oy).x;
|
|
|
+ item.geometry.y += this.oToLL(this.data.ox, this.data.oy).y;
|
|
|
+ item.symbol = {
|
|
|
+ type: "text",
|
|
|
+ color: "white",
|
|
|
+ haloColor: "black",
|
|
|
+ haloSize: "1px",
|
|
|
+ text: item.attributes.code,
|
|
|
+ xoffset: 0,
|
|
|
+ yoffset: -10,
|
|
|
+ font: {
|
|
|
+ size: 12,
|
|
|
+ // family: "Josefin Slab",/
|
|
|
+ weight: "bold"
|
|
|
+ }
|
|
|
+ };
|
|
|
+ let graphic = new Graphic(item);
|
|
|
+ text_graphics.push(graphic);
|
|
|
+ text_graphicsLayer.add(graphic);
|
|
|
+ },
|
|
|
+ // 添加线段
|
|
|
+ addLine: function(jsonItem) {
|
|
|
+ let item = JSON.parse(JSON.stringify(jsonItem));
|
|
|
+ item.geometry.type = "polyline";
|
|
|
+ item.geometry.spatialReference = SpatialReference.WGS84;
|
|
|
+ item.geometry.paths.forEach(item => {
|
|
|
+ item[0] += this.oToLL(this.data.ox, this.data.oy).x;
|
|
|
+ item[1] += this.oToLL(this.data.ox, this.data.oy).y;
|
|
|
+ });
|
|
|
+ item.symbol = {
|
|
|
+ type: "simple-line",
|
|
|
+ color: "#05bb4c",
|
|
|
+ width: item.attributes.width,
|
|
|
+ }
|
|
|
+ let graphic = new Graphic(item);
|
|
|
+ line_graphics.push(graphic);
|
|
|
+ line_graphicsLayer.add(graphic);
|
|
|
+ },
|
|
|
+ addFanByJson: function(jsonObj, lineJsonObj) {
|
|
|
+ // jsonObj.forEach(item => {
|
|
|
+ // this.addImgPoint(item);
|
|
|
+ // });
|
|
|
+ lineJsonObj.forEach(item => {
|
|
|
+ this.addLine(item);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ goto: function(point) {
|
|
|
+ view.goTo({
|
|
|
+ center: point
|
|
|
+ }).catch(function(error) {
|
|
|
+ if (error.name != "AbortError") {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 生命周期钩子
|
|
|
+ beforeCreate() {
|
|
|
+ // 创建前
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ // 创建后
|
|
|
+ },
|
|
|
+ beforeMount() {
|
|
|
+ // 渲染前
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // 渲染后
|
|
|
+ basemap = null;
|
|
|
+ map = null;
|
|
|
+ view = null;
|
|
|
+ point_graphicsLayer = null;
|
|
|
+ line_graphicsLayer = null;
|
|
|
+ text_graphicsLayer = null;
|
|
|
+ img_graphicsLayer = null;
|
|
|
+ html_graphicsLayer = null;
|
|
|
+ point_graphics = [];
|
|
|
+ line_graphics = [];
|
|
|
+ text_graphics = [];
|
|
|
+ img_graphics = [];
|
|
|
+ html_graphics = [];
|
|
|
+ this.initMap();
|
|
|
+ },
|
|
|
+ beforeUpdate() {
|
|
|
+ // 数据更新前
|
|
|
+ },
|
|
|
+ updated() {
|
|
|
+ // 数据更新后
|
|
|
+ },
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less">
|
|
|
+ .arcgis {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ &.pointer {
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ #viewDiv {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 1;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ #marker {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 2;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .arcgis-marker {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|