/* * @Author: your name * @Date: 2022-01-11 13:45:12 * @LastEditTime: 2024-08-01 10:21:14 * @LastEditors: 纪泽龙 jizelong@qq.com * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @FilePath: /test/hello-world/src/utils/mapClass.js */ import { pipeColor, svgUrl, svgAlarm } from "@/utils/mapClass/config.js"; // 编辑类 // 在地图上新增的设备可以直接编辑, // 已经保存完成的设备需要点编辑才可以编辑 export class EditorMap { // 地图的对象实例 map = null; // 外部传进来的中心店 center = null; // 父vue的实例 vue = null; // 操作 新建,编辑,删除,编辑跟删除只对已经在图上的设备有效 默认值:0, 新建:1,编辑:2, 删除: 3。 // 新建的时候会把未保存的线条清空 control = 0; // 鼠标事件对象,用来将点跟线上图 mousetool = null; // 当前正在手动绘制的对象 nowMouseTarget = null; // 当线mousetool线被按下的时候的flag 当线被按下的时候为true,就不询问是否删除了 mosueToolPolineDownFlag = false; // 绘制marer的时候的配置,在绘制完挂载事件的时候需要使用 mouseToolMarkerOptions = null; // 绘制poline的时候的配置,在绘制完挂载事件的时候需要使用 mouseToolPolineOptions = null; // 存放所有的设备的数组集合,这是一个对象,对象里面是各种设备的数组 allDevice = {}; // 存放所有的管道 pipeArr = {}; // 报警设备的对象 alarmObj = {}; // 当前的infowindow的组件 infowindowComponent = null; // infowindow本身 infowindow = null; //居民用户-用户列表图层 detectorUserlabelsLayer = null; //商业用户-用户列表图层 businessDetectorUserlabelsLayer = null; //调压箱-地图标注层 tyxlabelsLayer = null; //阀门井-地图标注层 fmjlabelLayer = null; //场站-地图标注层 czlabelLayer = null; //监控-地图标注层 videolabelLayer = null; //餐饮单位液化气用户 deviceUserlableLayer = null; // 通过搜索出来的设备,用它存 searchDevice = null; selarr = []; constructor(contaienr, config = {}, vue) { this.map = new AMap.Map(contaienr, { viewMode: "3D", center: [114.684979, 38.038292], layers: [AMap.createDefaultLayer()], // layers 字段为空或者不赋值将会自动创建默认底图。 zoom: 14, zooms: [3, 20], ...config, }); const { center } = config; this.center = center; this.vue = vue; this.init(config); } init(config) { // 地图事件 this.mapEvent(); // 手动点线上图准备,编辑模式 this.mouseAddDevice(); // this.mouseAddMarker(); // this.mouseAddPipeline(); // 地图边界 this.map.getCity((res) => { const city = res.district; this.mapBound(city, config.maskFLag); }, this.center); } mapBound(city, maskFLag) { var district = new AMap.DistrictSearch({ extensions: "all", // 返回行政区边界坐标等具体信息 level: "district", // 设置查询行政区级别为 区 }); district.search(city, (status, result) => { // 获取朝阳区的边界信息 var bounds = result.districtList[0].boundaries; var polygons = []; if (bounds) { for (var i = 0, l = bounds.length; i < l; i++) { //生成行政区划polygon // new AMap.Polygon({ // map: this.map, // strokeWeight: 2, // path: bounds[i], // fillOpacity: 1, // fillColor: "transparent", // strokeColor: "#09f", // }); new AMap.Polyline({ map: this.map, strokeWeight: 2, strokeColor: "#09f", strokeStyle: "dashed", path: bounds[i], }); // polygons.push(polygon); } if (maskFLag) { let mask = new AMap.Polygon({ path: bounds[0], // 边界坐标点集合 // fillColor: "#000000", // 填充色 // fillOpacity: 0.8, // 填充透明度 strokeStyle: "dashed", strokeWeight: 0, // 边框宽度,设为 0 表示没有边框 zIndex: 100, // 显示优先级,越大越靠上层 }); // 添加遮罩层到地图 this.map.add(mask); // this.map.setMapStyle('amap://styles/dark'); // this.map.setMask([mask]); } } }); } // map的事件监听 mapEvent() { this.map.on("click", () => { // mousetool对象画出的对象的操作 // 如果有手动绘制对象,要手动清楚一下,因为画线的时候不好清除旧线,这其实是用来清楚旧线的 // 当画出来的线被mousedown,不删除,但是mouseToolPipeLineFlag要归位,在移出线的时候统一归位 // 如果对象是marker,直接删除 if (this.nowMouseTarget?.type == "AMap.Marker") { this.mouseToolDrawClear(); } else { // 当地图上已经画了线,并且没有点在线上,询问是否删除 if (this.nowMouseTarget && !this.mosueToolPolineDownFlag) { this.confirm("是否重新绘制管道", { type: "warning" }) .then(() => { // 删除原来的线 this.mouseToolDrawClear(); // 鼠标事件开启,并且赋值原来的属性,this.mouseToolMarkerOptions是开启绘制的时候记录的 this.mousetool.polyline(this.mouseToolPolineOptions); }) .catch(() => {}); } } }); this.map.on("mousedown", () => { console.log("mapONMousedown"); if (this.detectorUserlabelsLayer != null) { const detectorUserHas = this.selarr.indexOf(6) >= 0; if (detectorUserHas) { this.detectorUserlabelsLayer.hide(); } } //商业用户 if (this.businessDetectorUserlabelsLayer != null) { const businessDetectorUserHas = this.selarr.indexOf(61) >= 0; if (businessDetectorUserHas) { this.businessDetectorUserlabelsLayer.hide(); } } // 调压箱 if (this.tyxlabelsLayer != null) { const tyxHas = this.selarr.indexOf(2) >= 0; if (tyxHas) { this.tyxlabelsLayer.hide(); } } // 阀门井 if (this.fmjlabelLayer != null) { const fmjHas = this.selarr.indexOf(3) >= 0; if (fmjHas) { this.fmjlabelLayer.hide(); } } // 场站 if (this.czlabelLayer != null) { const czHas = this.selarr.indexOf(4) >= 0; if (czHas) { this.czlabelLayer.hide(); } } // 监控 if (this.videolabelLayer != null) { const videoHas = this.selarr.indexOf(5) >= 0; if (videoHas) { this.videolabelLayer.hide(); } } // 餐饮单位液化气用户 if (this.deviceUserlableLayer != null) { const deviceUserHas = this.selarr.indexOf(18) >= 0; if (deviceUserHas) { this.deviceUserlableLayer.hide(); } } }); this.map.on("mouseup", () => { //居民用户 if (this.detectorUserlabelsLayer != null) { const detectorUserHas = this.selarr.indexOf(6) >= 0; if (detectorUserHas) { this.detectorUserlabelsLayer.show(); } } //商业用户 if (this.businessDetectorUserlabelsLayer != null) { const businessDetectorUserHas = this.selarr.indexOf(61) >= 0; if (businessDetectorUserHas) { this.businessDetectorUserlabelsLayer.show(); } } // 调压箱 if (this.tyxlabelsLayer != null) { const tyxHas = this.selarr.indexOf(2) >= 0; if (tyxHas) { this.tyxlabelsLayer.show(); } } // 阀门井 if (this.fmjlabelLayer != null) { const fmjHas = this.selarr.indexOf(3) >= 0; if (fmjHas) { this.fmjlabelLayer.show(); } } // 场站 if (this.czlabelLayer != null) { const czHas = this.selarr.indexOf(4) >= 0; if (czHas) { this.czlabelLayer.show(); } } // 监控 if (this.videolabelLayer != null) { const videoHas = this.selarr.indexOf(5) >= 0; if (videoHas) { this.videolabelLayer.show(); } } // 餐饮单位液化气用户 if (this.deviceUserlableLayer != null) { const deviceUserHas = this.selarr.indexOf(18) >= 0; if (deviceUserHas) { this.deviceUserlableLayer.show(); } } }); this.map.on("moveend", () => { console.log("地图停止移动"); if (this.flag) { console.log("弹框"); this.flag = false; } }); this.map.on("movestart", () => { console.log("地图开始移动"); return; //居民用户 }); // this.map.on('zoomchange', () => { // //获取当前最新的地图层级 // let Zoom = this.map.getZoom() // /** // * 地图层级发生改变后操作 // * */ // console.log(Zoom); // }) window.panTo = () => { this.flag = true; this.map.panTo([116.428285, 39.886129]); }; } // 弹框工具 confirm(message, obj) { return this.vue.$confirm(message, obj); } // 改变操作状态 changeControl(num) { this.control = num; } // 点线编辑上图准备 mouseAddDevice() { this.map.plugin(["AMap.MouseTool"], () => { this.mousetool = new AMap.MouseTool(this.map); }); setTimeout(() => { this.mouseDrawEvent(); }, 2000); // 挂载绘制结束的事件 } // 点或者线上图结束后触发的事件 mouseDrawEvent() { this.mousetool.on("draw", (e) => { const target = e.obj; // console.log([target._position.lng, target._position.lat]); const { type: targetType } = target; // 当这个点是marker的时候 if (targetType == "AMap.Marker") { this.mouseToolMarkerEvent(target); } else { // 如果是线,挂上编辑 this.lineEditor(target); this.mousetool.close(); this.mouseToolPolineEvent(target); console.log(targetType, "当前对象是管道"); } this.nowMouseTarget = target; }); } // 绘制marker结束后,在marker身上添加的事件 mouseToolMarkerEvent(target) { // 由于画出来的marker点击会换位置,所以当移入的时候删除绘制事件,移出去在增加绘制事件 target.on("mouseover", (e) => { // 鼠标事件关闭 this.mousetool.close(false); }); target.on("mouseout", (e) => { // 这里不方便获取原来的属性,因为position不好解决,还是设置一个值吧 // 鼠标事件开启,并且赋值原来的属性,this.mouseToolMarkerOptions是开启绘制的时候记录的 this.mousetool.marker(this.mouseToolMarkerOptions); }); // 点 target.on("click", (e) => { // 弹框 }); } // 挂上线以及线的事件 lineEditor(line) { // line.editor && line.editor.close(); // 当前点击次数,1次为编辑,2次为弹框 line.editorNum = 0; line.editor = new AMap.PolyEditor(this.map, line); } // 绘制管道的时候,挂载的事件 mouseToolPolineEvent(target) { // 线按下的时候会变成编辑,mousetool事件会清空 移出线的时候 在把polyline事件加上 target.on("mouseover", (e) => { // 鼠标事件关闭 // this.mousetool.close(false); }); target.on("mouseout", (e) => { // 有时候按在线上移动地图,map点击事件中mosueToolPolineDownFlag无法归位,在这里归位 this.mosueToolPolineDownFlag = false; // 鼠标事件开启,并且赋值原来的属性,this.mouseToolMarkerOptions是开启绘制的时候记录的 // this.mousetool.polyline(this.mouseToolPolineOptions); }); // 线 target.on("mousedown", (e) => { const line = e.target; // mosueTool按下的flag,按在线上,不询问是否删除 this.mosueToolPolineDownFlag = true; // 按下的时候要关闭事件 this.mousetool.close(false); // 如果当前状态不是编辑,则进入编辑状态 if (line.editorNum < 1) { // 打开并且++ line.editor.open(); line.editorNum++; } else { // 这里就要弹框了 console.log(line.getPath()); } }); } // 设备点击上图开启 mouseAddMarker(markerObj = {}) { // 清空已经绘制完的对象 this.mousetoolClose(true); // 记录一下配置项,在挂载点击的时候,需要使用 this.mouseToolMarkerOptions = { draggable: true, ...markerObj, }; this.mousetool.marker(this.mouseToolMarkerOptions); } // 管线点击上图开启 mouseAddPipeline(pipeObj = {}) { this.mousetoolClose(true); // 开始画线 this.mosuetoolPolineFlag = true; this.mouseToolPolineOptions = { strokeWeight: 5, ...pipeObj, }; this.mousetool.polyline(this.mouseToolPolineOptions); } // 手动清除map上绘制的对象 mouseToolDrawClear() { if (this.nowMouseTarget) { this.map.remove(this.nowMouseTarget); // 如果有editor,则关闭 this.nowMouseTarget.editor && this.nowMouseTarget.editor.close(); this.nowMouseTarget = null; } } // 关闭点击上图事件 true清除之前绘制的图像,false 仅关闭上图事件 mousetoolClose(boolean) { // 清空地图上的绘制对象的同时,也要清楚这个nowMouseTarget控制对象 if (this.nowMouseTarget) { // 如果有editor,则关闭 this.nowMouseTarget.editor && this.nowMouseTarget.editor.close(); this.nowMouseTarget = null; } this.mousetool.close(boolean); } /** * * * * * * * 地图上add设备 * * * @description: * @param {*} deviceData marker的数据 * @param {*} compontent marker点击弹出的infowindow的组件 * @return {*} */ addDevice(deviceData, compontent, showBool = true) { const { longitude: lng, latitude: lat, iconType } = deviceData; const icon = svgUrl[iconType]; let device = this.createMarker({ map: this.map, anchor: "bottom-center", icon, position: [lng, lat], extData: deviceData, alwaysRender: false, // label:{ // content:123, // direction:"top", // } }); // if (!showBool) { // device.hide(); // } // 如果没有有这个公司的数组,就创建,有就直接push // if (!Array.isArray(this.allDevice[iconType])) { // this.allDevice[iconType] = []; // } // this.allDevice[iconType].push(device); this.searchDevice = device; // 设备的事件函数 this.deviceEvent(device, compontent); } deviceEvent(device, compontent) { device.on("click", (e) => { const target = e.target; // 如果control==0就是默认值,没有使用123功能,就显示infowindow if (this.control == 0) { this.markerClick(target, compontent); } else if (this.control == 2) { // 2是已经上图的设备拥有的编辑功能 } else if (this.control == 3) { // 3是删除操作 } }); // device.on("mouseover", (e) => { // const target = e.target; // const data = target.getExtData(); // console.log(data); // const name = // data.nickName || // data.deviceName || // data.videoName || // data.stationName || // data.time; // target.setLabel({ content: name, direction: "top" }); // }); // device.on("mouseout", (e) => { // const target = e.target; // const data = target.getExtData(); // target.setLabel({ content: "" }); // }); } /** 点击marker出现infowindow * @description: * @param {*} target 点击的对象 * @param {*} compontent marker点击弹出的infowindow的组件 * @return {*} */ markerClick(target, compontent) { // 为了删除搜索上图对象 // this.infowindowClose(); const deviceExtData = target.getExtData(); const { longitude: lng, latitude: lat } = deviceExtData; // 创建一个可以控制的组件,将其dom插入infowindow this.infowindowComponent = this.createInfowindowDom( this.vue, this, deviceExtData, compontent ); // 没恩么用,控制台测试的时候用着玩的 window.func = () => { const { longitude: lng, latitude: lat } = target.getExtData(); const cd = { id: 1, name: "9", lng, lat, }; this.infowindowComponentChange(cd); target.setExtData(cd); }; this.infowindow = new AMap.InfoWindow({ isCustom: true, content: this.infowindowComponent.$el, position: [lng, lat], anchor: "middle-left", offset: [30, -45], // anchor: "middle-left", // offset: [40, -10], }); this.infowindow.open(this.map); } // 创建要加入到infowindow里的 createInfowindowDom(vueRoot, mapClass, deviceData, compontent) { const Component = this.vue.$Vue.extend(compontent, {}); return new Component({ data() { return { // 当前vue实例 vueRoot, // 自己写的map类 mapClass, // 数据 deviceData, }; }, }).$mount(); } // 当前显示的infowindow内部的数据发生变化,一般在socket传回数据的时候使用 infowindowComponentChange(data) { this.infowindowComponent.deviceData = data; } // 创建marker createMarker(MarkerOptions) { return new AMap.Marker(MarkerOptions); // return new AMap.MarkerClusterer(MarkerOptions); } filterSelectPipe(id, mediumComponent, lng, lat) { this.pipeArr[1].forEach((pipe) => { const deviceExtData = pipe.getExtData(); if (deviceExtData.pipeId === id) { //设置颜色 const options = pipe.getOptions(); options.strokeColor = "blue"; // options.strokeWeight =4; pipe.setOptions(options); // 创建一个可以控制的组件,将其dom插入infowindow this.infowindowComponent = this.createInfowindowDom( this.vue, this, deviceExtData, mediumComponent ); this.infowindow = new AMap.InfoWindow({ isCustom: true, content: this.infowindowComponent.$el, position: [lng, lat], // anchor: "top-left", // offset: [20, -15], anchor: "middle-left", offset: [20, 0], }); this.infowindow.open(this.map); } }); } /** * 地图上添加 餐饮单位液化气用户 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} compontent * @param {*} showBool */ labelsLayerMarksDeviceUserGoMap(mapData, compontent, showBool = true) { if (mapData != null) { const hashMap = new Map(); this.deviceUserlableLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[18], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; mapData.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); this.deviceUserlableLayer.add(markers); this.map.add(this.deviceUserlableLayer); if (!showBool) { this.deviceUserlableLayer.hide(); } } } /** * 地图上添加监控 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} compontent * @param {*} showBool */ labelsLayerMarksVideoGoMap(mapData, compontent, showBool = true) { if (mapData != null) { const hashMap = new Map(); this.videolabelLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[5], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; mapData.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); this.videolabelLayer.add(markers); this.map.add(this.videolabelLayer); if (!showBool) { this.videolabelLayer.hide(); } } } /** * 地图上添加场站 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} compontent * @param {*} showBool */ labelsLayerMarksCzGoMap(mapData, compontent, showBool = true) { if (mapData != null) { const hashMap = new Map(); this.czlabelLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[4], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; mapData.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); this.czlabelLayer.add(markers); this.map.add(this.czlabelLayer); if (!showBool) { this.czlabelLayer.hide(); } } } /** * 地图上添加阀门井 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} compontent * @param {*} showBool */ labelsLayerMarksFmjGoMap(mapData, compontent, showBool = true) { if (mapData != null) { const hashMap = new Map(); this.fmjlabelLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[3], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; mapData.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); this.fmjlabelLayer.add(markers); this.map.add(this.fmjlabelLayer); if (!showBool) { this.fmjlabelLayer.hide(); } } } /** * 地图上添加调压箱 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} compontent * @param {*} showBool */ labelsLayerMarksTysGoMap(mapData, compontent, showBool = true) { if (mapData != null) { const hashMap = new Map(); this.tyxlabelsLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[2], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; mapData.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); this.tyxlabelsLayer.add(markers); this.map.add(this.tyxlabelsLayer); if (!showBool) { this.tyxlabelsLayer.hide(); } } } /** * 地图上添加用户数据 海量标注 LabelMarker 方式 * @param {*} detectorUserData * @param {*} component * @param {*} showBool */ labelsLayerMarksDetectorUserList(mapData, compontent, showBool = true) { if (mapData !== null && mapData !== undefined) { const hashMap = new Map(); for (var key in mapData) { var value = mapData[key]; var jsonValue = JSON.stringify(value); var jsonValueArr = JSON.parse(jsonValue); //居民用户 if (key === "6") { this.detectorUserlabelsLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[6], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; if (jsonValueArr !== null && jsonValueArr !== undefined) { jsonValueArr.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 1, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); } this.detectorUserlabelsLayer.add(markers); this.map.add(this.detectorUserlabelsLayer); if (!showBool) { this.detectorUserlabelsLayer.hide(); } //商业用户 } else if (key === "61") { this.businessDetectorUserlabelsLayer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, collision: false, //该层内标注是否避让 allowCollision: false, //不同标注层之间是否避让 }); //设置一个图标对象 const icon = { type: "image", //图标类型,现阶段只支持 image 类型 image: svgUrl[61], //可访问的图片 URL size: [44, 49], //图片尺寸 anchor: "center", //图片相对 position 的锚点,默认为 bottom-center }; var markers = []; if (jsonValueArr !== null && jsonValueArr !== undefined) { jsonValueArr.forEach((item) => { let longitude = item.longitude; let latitude = item.latitude; var userId = item.userId; icon.userId = userId; var curData = { position: [longitude, latitude], icon: icon, rank: 2, //避让优先级 }; hashMap.set(JSON.stringify(userId), item); //创建 LabelMarker const labelMarker = new AMap.LabelMarker(curData); // var marker = new AMap.Marker(curData); markers.push(labelMarker); labelMarker.on("click", (e) => { var opts = JSON.stringify(e.data.opts); var optsObj = JSON.parse(opts); var userId = JSON.stringify(optsObj.icon.userId); var extData = hashMap.get(userId); // 如果control==0就是默认值,没有使用123功能,就显示infowindow this.massMarksMarkerClick(extData, compontent); }); if (item.companyType) { labelMarker.filterData = { companyType: item.companyType, iconType: item.iconType, }; const iconType = item.iconType; if (!Array.isArray(this.allDevice[iconType])) { this.allDevice[iconType] = []; } this.allDevice[iconType].push(labelMarker); } }); } this.businessDetectorUserlabelsLayer.add(markers); this.map.add(this.businessDetectorUserlabelsLayer); if (!showBool) { this.businessDetectorUserlabelsLayer.hide(); } } } } } /** * 地图上添加用户数据 海量点标记 MassMarks 方式 * @param {*} detectorUserData * @param {*} component * @param {*} showBool */ addMassMarksDetectorUserGoMap(mapData, compontent, showBool = true) { if (mapData !== null && mapData !== undefined) { var style; for (var key in mapData) { var value = mapData[key]; var jsonValue = JSON.stringify(value); var jsonValueArr = JSON.parse(jsonValue); if ("6" === key) { style = [ { url: svgUrl[6], anchor: new AMap.Pixel(3, 3), size: new AMap.Size(11, 11), zIndex: 3, }, ]; } else if ("61" === key) { style = [ { url: svgUrl[6], anchor: new AMap.Pixel(3, 3), size: new AMap.Size(11, 11), zIndex: 3, }, ]; } var mass = new AMap.MassMarks(jsonValueArr, { opacity: 0.8, zIndex: 111, cursor: "pointer", style: style, }); //先一启动,直接显示 // if (!showBool) { // mass.hide(); // } mass.on("click", (e) => { var data = e.data; // 如果control==0就是默认值,没有使用123功能,就显示infowindow if (this.control == 0) { this.massMarksMarkerClick(data, compontent); } else if (this.control == 2) { // 2是已经上图的设备拥有的编辑功能 } else if (this.control == 3) { // 3是删除操作 } }); mass.setMap(this.map); } } } /** 点击marker出现infowindow- 大屏端 massMarks设置 * @description: * @param {*} target 点击的对象 * @param {*} compontent marker点击弹出的infowindow的组件 * @return {*} */ massMarksMarkerClick(data, compontent) { // 通过搜索上图的数据 this.infowindowClose(); // var detectorUserVO = data.tdetectorUserVO; // var lng = lnglatArray[0]; // var lat = lnglatArray[1]; // var detectorUserVO = {"userId":159843,"iconType":null,"userStatus":null,"nickName":"曾宪成","userType":"2","detectorCountList":[{"userId":159843,"iconType":null,"userStatus":null,"nickName":"曾宪成","userType":"2","detectorCountList":null,"detectorType":"工业探测器","detectorCount":1,"onLineNum":1,"offLineNum":0,"historyAlarmNum":0,"cancelAlarmNum":0,"processingAlarmNum":0,"address":"河北省-廊坊市-三河市-泃阳镇老厨小吃","longitude":117.06009,"latitude":39.991257,"linkman":"曾宪成","phone":"13172132000","email":null}],"detectorType":"工业探测器","detectorCount":1,"onLineNum":1,"offLineNum":0,"historyAlarmNum":0,"cancelAlarmNum":0,"processingAlarmNum":0,"address":"河北省-廊坊市-三河市-泃阳镇老厨小吃","longitude":117.06009,"latitude":39.991257,"linkman":"曾宪成","phone":"13172132000","email":null} let lng = data.longitude; let lat = data.latitude; // 创建一个可以控制的组件,将其dom插入infowindow this.infowindowComponent = this.createInfowindowDom( this.vue, this, data, compontent ); this.infowindow = new AMap.InfoWindow({ isCustom: true, content: this.infowindowComponent.$el, position: [lng, lat], anchor: "middle-left", // offset: [20, -10], offset: [20, 0], }); this.infowindow.open(this.map); } // 地图上add管道 addMediumPipeLine(objData, component, mediumConponent, search = false) { const { path, pipePressure, iconType, id } = objData; // 根据压力获取颜色 const color = pipeColor[pipePressure]; const pipe = this.createPipeLine({ id: id, path: eval(path), strokeWeight: objData.strokeWeight || 3, strokeColor: color, strokeOpacity: 0.1, extData: objData, cursor: "pointer", }); this.map.add(pipe); // pipe.hide(); if (!Array.isArray(this.pipeArr[iconType])) { this.pipeArr[iconType] = []; } this.pipeArr[iconType].push(pipe); // 当是搜索的时候 if (search) { this.searchDevice = pipe; } if (pipePressure == 1) { this.searchDevice.com = mediumConponent; this.pipeEvent(pipe, mediumConponent); } else { this.searchDevice.com = component; this.pipeEvent(pipe, component); } } // 地图上add管道 addPipeLine(objData, component) { const { path, pipePressure, iconType } = objData; // 根据压力获取颜色 const color = pipeColor[pipePressure]; const pipe = this.createPipeLine({ path: eval(path), strokeWeight: objData.strokeWeight || 4, strokeColor: color, extData: objData, cursor: "pointer", }); this.map.add(pipe); // pipe.hide(); if (!Array.isArray(this.pipeArr[iconType])) { this.pipeArr[iconType] = []; } this.pipeArr[iconType].push(pipe); // console.log(this.pipeArr); // this.map.panTo([path[0][0], path[0][1]]); this.pipeEvent(pipe, component); } createPipeLine(pipeLineOptions) { return new AMap.Polyline(pipeLineOptions); } pipeEvent(pipe, compontent) { pipe.on("mouseover", (e) => { const target = e.target; // 获取当前颜色 const options = target.getOptions(); options.strokeColor = "blue"; // options.strokeWeight =4; target.setOptions(options); }); pipe.on("mouseout", (e) => { if (this.infowindow) { var infowindowOptions = this.infowindow.getOptions(); if (infowindowOptions.visible) { var pipeData = this.infowindowComponent.deviceData; const target = e.target; var clickPipeId = pipeData.pipeId; const { pipeId } = target.getExtData(); if (clickPipeId === pipeId) return; } } const target = e.target; // 根据管道压力获取颜色 const { pipePressure } = target.getExtData(); const color = pipeColor[pipePressure]; // 获取当前颜色 const options = target.getOptions(); options.strokeColor = color; // options.strokeWeight =2; target.setOptions(options); }); pipe.on("click", (e) => { // 通过搜索上图的数据 this.infowindowClose(); const target = e.target; target.lnglat = e.lnglat; // 如果control==0就是默认值,没有使用123功能,就显示infowindow if (this.control == 0) { this.pipeClick(target, compontent); } else if (this.control == 2) { // 2是已经上图的设备拥有的编辑功能 } else if (this.control == 3) { // 3是删除操作 } }); } pipeClick(target, compontent) { const deviceExtData = target.getExtData(); const { lng, lat } = target.lnglat; console.log(target); // 创建一个可以控制的组件,将其dom插入infowindow this.infowindowComponent = this.createInfowindowDom( this.vue, this, deviceExtData, compontent ); // 没恩么用,控制台测试的时候用着玩的 // window.func = () => { // const { lng, lat } = target.getExtData(); // const cd = { // id: 1, // name: "9", // lng, // lat, // }; // this.infowindowComponentChange(cd); // target.setExtData(cd); // }; this.infowindow = new AMap.InfoWindow({ isCustom: true, content: this.infowindowComponent.$el, position: [lng, lat], // anchor: "top-left", // offset: [20, -15], anchor: "middle-left", offset: [20, 0], }); this.infowindow.open(this.map); } infowindowClose() { if (!this.infowindow) return; //关闭的时候恢复颜色 var data = this.infowindowComponent.deviceData; var pipePressure = data.pipePressure; var id = data.pipeId; const color = pipeColor[pipePressure]; this.pipeArr[1].forEach((pipe) => { const deviceExtData = pipe.getExtData(); if (deviceExtData.pipeId === id) { console.log("改"); //设置颜色 const options = pipe.getOptions(); options.strokeColor = color; // options.strokeWeight =4; pipe.setOptions(options); } }); this.infowindow.close(); // 通过搜索上图的数据 this.clearSearchDevice(); } // 设备以及公司过滤 allfilter(companyArr, typeArr) { console.log(typeArr, this.pipeArr); for (let pipeItem in this.pipeArr) { this.pipeArr[pipeItem].forEach((pipe) => { const data = pipe.getExtData(); console.log(typeArr.indexOf(1)); if ( companyArr.indexOf(data.companyType + "") >= 0 && typeArr.indexOf(1) >= 0 ) { pipe.show(); } else { pipe.hide(); } }); } console.log(this.allDevice); // return; for (let deviceItem in this.allDevice) { this.allDevice[deviceItem].forEach((device) => { const data = device.filterData || device.getExtData(); console.log("data", data.filterData); // console.log(data.iconType); // 设备过滤受到bigwindow页面的的两种制约,companyArr, typeArr 两个数组制约显示隐藏 // 燃气没有公司,所以没有device.companyType不收到公司的控制 const companyHas = companyArr.indexOf(data.companyType + "") >= 0; // 设备存在 受到设备按钮限制 const deviceHas = typeArr.indexOf(+data.iconType) >= 0; // 如果是燃气公司的话,不受按钮限制 const enterprise = data.iconType == 7 || data.iconType == 8; // 必须设备存在数组里,才会显示设备 !data.companyType代表用户不受公司制约 if (enterprise || (deviceHas && (companyHas || !data.companyType))) { device.show(); // console.log(data.iconType,companyHas,deviceHas,enterprise,'show') } else { device.hide(); // console.log(data.iconType,companyHas,deviceHas,enterprise,"hide") } }); } // 判断是否需要显示 居民用户 const detectorUserHas = typeArr.indexOf(6) >= 0; this.selarr = typeArr; if (this.detectorUserlabelsLayer != null) { if (detectorUserHas) { this.detectorUserlabelsLayer.show(); } else { this.detectorUserlabelsLayer.hide(); } } // 判断是否需要显示 商业用户 const businessDetectorUserHas = typeArr.indexOf(61) >= 0; if (this.businessDetectorUserlabelsLayer != null) { if (businessDetectorUserHas) { this.businessDetectorUserlabelsLayer.show(); } else { this.businessDetectorUserlabelsLayer.hide(); } } // 判断是否需要显示 调压箱 const tyxHas = typeArr.indexOf(2) >= 0; if (this.tyxlabelsLayer != null) { if (tyxHas) { this.tyxlabelsLayer.show(); } else { this.tyxlabelsLayer.hide(); } } // 判断是否需要显示 阀门井 const fmjHas = typeArr.indexOf(3) >= 0; if (this.fmjlabelLayer != null) { if (fmjHas) { this.fmjlabelLayer.show(); } else { this.fmjlabelLayer.hide(); } } //判断是否需要显示 场站 const czHas = typeArr.indexOf(4) >= 0; if (this.czlabelLayer != null) { if (czHas) { this.czlabelLayer.show(); } else { this.czlabelLayer.hide(); } } //判断是否需要显示 监控 const videoHas = typeArr.indexOf(5) >= 0; if (this.videolabelLayer != null) { if (videoHas) { this.videolabelLayer.show(); } else { this.videolabelLayer.hide(); } } //判断是否需要显示 餐饮单位液化气用户 const deviceUserHas = typeArr.indexOf(18) >= 0; if (this.deviceUserlableLayer != null) { if (deviceUserHas) { this.deviceUserlableLayer.show(); } else { this.deviceUserlableLayer.hide(); } } } // 普通调用方法 // 设备报警 deviceAlarm(obj) { // 设备的类型 const { iconType } = obj; const publicId = obj.userId || obj.deviceId; // 找到这个设备所属的空间 const device = this.allDevice[iconType].filter( (item) => (item.getExtData().userId || item.getExtData().deviceId) == publicId )[0]; // 更改的icon const icon = svgAlarm[iconType]; device.setIcon(icon); device.setzIndex(13); // 将旧的值缓存一下 // device.oldData = device.getExtData(); // device.setExtData(obj); // 可能出现infoWindow数据变化 this.alarmInfowindowChange(obj); if (!this.alarmObj[iconType]) { this.alarmObj[iconType] = []; } const ind = this.alarmObj[iconType].indexOf(publicId); if (ind < 0) { this.alarmObj[iconType].push(publicId); } } // 报警时候,可能发生infowindowComponent存在,也要变化 alarmInfowindowChange(obj) { if (!this.infowindowComponent) return; // 如果infowindow是打开的,就改变里面的数据 必须是 调压箱2 阀门3 用户6 才会发生变化电话 const infowindowDeviceType = [2, 3, 6].includes( this.infowindowComponent.deviceData.iconType ); // 如果存在userId就用userId,如果存在deviceId就用deviceId const infowindowDeviceId = this.infowindowComponent.deviceData.userId || this.infowindowComponent.deviceData.deviceId; // 如果存在userId就用userId,如果存在deviceId就用deviceId const objId = obj.userId || obj.deviceId; // 如果两个值匹配,才可以改变infowindow身上的组件 const infowindowComponentHas = infowindowDeviceId == objId; if ( this.infowindowComponent && infowindowDeviceType && infowindowComponentHas ) { // this.infowindowComponentChange(obj); if (this.infowindowComponent.http) { this.infowindowComponent.myHttp(); } } } //如果传过来的报警设备中,有不在deviceAlarm中,就是恢复的设备恢复 relieveAlarm(alarmObj) { // 把报警数组改变结构,如果有userId就是用户,如果有deviceId就是其他设备 const httpObj = {}; alarmObj.forEach((item) => { const publicId = item.userId || item.deviceId; if (!Array.isArray(httpObj[item.iconType])) { httpObj[item.iconType] = []; } httpObj[item.iconType].push(publicId); }); // 循环现有报警设备 for (let iconType in this.alarmObj) { const arr = this.alarmObj[iconType]; // 循环现有报警设备 for (let i = 0; i < arr.length; i++) { // 看看现有报警设备中有没有不在 报警数组中的值,有就恢复可能是userId,也可能是deviceId const publicId = arr[i]; // 看看接口传来的数据中还有没有这些Id,如果没有了,就是修好了 const hasId = httpObj[iconType]?.includes(publicId); // 如果已经不在报警数组中,就要去大数组中找他,利用userId // 如果id不存在了,说明不报警了 if (!hasId) { // 过滤出来这个要恢复的设备 const device = this.allDevice[iconType].filter( (item) => (item.getExtData().userId || item.getExtData().deviceId) == publicId )[0]; // 恢复 const icon = svgUrl[iconType]; device.setIcon(icon); // 赋值 // const deviceData = { ...device.oldData }; // device.setExtData(deviceData); // device.oldData = null; // 如果infowindow是打开的 this.alarmInfowindowChange(device.getExtData()); // 在arr中删掉 arr.splice(i, 1); // 由于删掉了当前,所以要--恢复位置 i--; } } } } // ws协议方法 wsAlarm(obj) { const { iconType, userId, userStatus } = obj; const decice = this.allDevice[iconType].filter( (item) => item.getExtData().userId == userId )[0]; let icon = null; // 2报警,1恢复 if (userStatus == 2) { icon = svgAlarm[iconType]; device.oldData = device.getExtData(); device.setExtData(obj); } else if (userStatus == 1) { icon = svgUrl[iconType]; const oldData = device.oldData; device.setExtData(oldData); device.oldData = null; } decice.setIcon(icon); } // 卫星图切换 satellite = null; changeMap(bool) { // 卫星, if (!bool) { if (this.satellite) return; this.satellite = new AMap.TileLayer.Satellite(); this.map.addLayer(this.satellite); } else { if (this.satellite) { this.map.removeLayer(this.satellite); this.satellite = null; } } } // 搜索设备或者管道上图 onlySearchDeviceOrLine(type, deviceOrLine) {} // 轨迹回放 /** * @description: * @param {*} vehicleId 设备id * @param {*} path 轨迹回访率丼 * @return {*} */ backTrack(vehicleId, path, times, component) { this.infowindowClose(); AMap.plugin("AMap.MoveAnimation", () => { let marker = this.allDevice[9].filter( (item) => item.getExtData().vehicleId == vehicleId )[0]; // 绘制轨迹 marker.polyline = new AMap.Polyline({ map: this.map, path, showDir: true, strokeColor: "#28F", //线颜色 // strokeOpacity: 1, //线透明度 strokeWeight: 6, //线宽 // strokeStyle: "solid" //线样式 }); marker.passedPolyline = new AMap.Polyline({ map: this.map, strokeColor: "#AF5", //线颜色 strokeWeight: 6, //线宽 }); marker.on("moving", (e) => { marker.passedPolyline.setPath(e.passedPath); // this.map.setCenter(e.target.getPosition(), true); // console.log(getPosition()); }); // 每个path的点 // marker.pointArr = []; // carTarget //点击的时候,先传进来一个点 const carPathData = { ...marker.getExtData(), time: times[0] }; carPathData.iconType = 14; this.addDevice(carPathData, component); // marker.pointArr.push(point); marker.on("moveend", (e) => { // this.addDevice(carPathData,carBackComponent); // 如果不是最后一个点,就创建一个新的worderpoint,如果是就不创建,并且把自身删除 let z = { longitude: e.pos[0], latitude: e.pos[1], iconType: 14, time: times[e.index], }; // if (e.index == path.length - 1) { // point = this.addDevice(z, null); // } else { this.addDevice(z, component); // workPoint.infoWindow.open(map,e.passedPos); // } console.log("定点", e); }); marker.moveAlong(path, { // 每一段的时长 duration: 8000, //可根据实际采集时间间隔设置 // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置 autoRotation: true, }); }); } setCenter(path) { this.map.setCenter(path, true); } clearbackTrack(vehicleId) { // let marker = this.allDevice[9].filter( // (item) => item.getExtData().vehicleId == vehicleId // )[0]; this.allDevice["9"]?.forEach((item) => { if (item) { // 停止运动 item.stopMove(); // 删除每个点 console.log(item.pointArr); if (item.polyline) { this.map.remove(item.polyline); } if (item.passedPolyline) { this.map.remove(item.passedPolyline); } this.map.remove(item); } }); // 最后把数组清空 this.allDevice["9"] = []; // 把car的路径点也清空 this.allDevice["14"]?.forEach((iten) => { this.map.remove(iten); }); this.allDevice["14"] = []; this.infowindowClose(); } // 搜索的管道被点击 pipeClicked(lnglat) { this.searchDevice.lnglat = lnglat; this.map.panTo([lnglat.lng, lnglat.lat], 0); this.searchDevice.iconType == 1; this.pipeClick(this.searchDevice, this.searchDevice.com); const options = this.searchDevice.getOptions(); options.strokeColor = "blue"; // options.strokeWeight =4; this.searchDevice.setOptions(options); } markerClicked(lnglat, com) { console.log(this.searchDevice.getExtData()); this.markerClick(this.searchDevice, com); this.map.panTo(lnglat, 0); } clearSearchDevice() { if (this.searchDevice) { this.map.remove(this.searchDevice); this.searchDevice = null; } } piprOpacityChange(num) { for (let item in this.pipeArr) { this.pipeArr[item].forEach((pipe) => { const options = pipe.getOptions(); pipe.setOptions({ ...options, strokeOpacity: num }); }); } console.log(123) } // searchPipeClear() { // const { pipePressure } = this.searchDevice.getExtData(); // const color = pipeColor[pipePressure]; // // 获取当前颜色 // const options = this.searchDevice.getOptions(); // options.strokeColor = color; // // options.strokeWeight =2; // this.searchDevice.setOptions(options); // } }