阅读量:0
- 拖动左侧图标到地图上某个位置,在地图上创建该类型的点,存储在list
- 拖拽点移动,重新更新其坐标
- 编辑点的大小及角度,清除之前的重新创建新的点
- 删除点,清除点,但数据不能清除,更改show
- 最后保存list数据并截图保存
- 下次进来渲染点重新编辑
<template> <div class="index5 w100 h100 white relative"> <canvas id="myCanvas" style="display: none; width: 100vw; height: 100vh" ></canvas> <img src="./components/img/home.png" alt="" class="home pointer" @click="$router.back()" /> <!-- 地图区域 --> <div id="containerMap" class="w100 h100" ref="htmlImg"></div> <!-- 左侧菜单 --> <div v-show="showMenu" class="left h80 absolute animate__animated animate__slideInLeft animate__fast" > <div class="w100 pdRem-20 h100"> <dv-border-box-8 :color="['rgba(2, 208, 249,.5)', '#0dcff2']" backgroundColor="rgba(4, 33, 66,.8)" > <div class="plrRem-20 ptbRem-10 flex flex-column w100 h100"> <div class="title flex_l mtb-20"> <img src="./components/img/index1-title.png" alt="" /> 作战标绘 </div> <div class="flex flex-wrap w100"> <div class="item plr-20 text-center mb-20 pointer" style="width: 50%" v-for="(item, index) in tab" :key="index" > <!-- ☆☆☆☆☆ 拖拽图片默认会打开窗口预览,换成背景图即可 --> <!-- <img :src="item.icon" alt="" style="width: 50px" /> --> <div draggable="true" @dragstart="onDragStart" @dragend="onDragEnd" :data-index="index" class="img-bg" :style="{ backgroundImage: `url(${item.icon})`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: 'cover', backgroundAttachment: 'local', }" ></div> <div class="mt-4">{{ item.text }}</div> </div> </div> <img src="./components/img/index5-btn4.png" alt="" style="width: 140px; margin: 60px auto 20px" @click="issueImg" class="pointer" /> </div> </dv-border-box-8> </div> </div> <!-- 右下控制 --> <div v-show="showMenu && showEdit" class="right absolute animate__animated animate__slideInLeft animate__fast pdRem-20" > <div class="w100 h100 editBox ptRem-14 pbRem-10 plRem-10 prRem-20"> <div class="plrRem-20 ptbRem-10 flex flex-column w100 h100 editContent"> <div class="title flex_l mtb-10"> <img src="./components/img/index1-title.png" alt="" /> 标绘属性 </div> <div class="plrRem-20 mbRem-20 flex flex-column"> <div class="flex1"> <div style="width: 60px; font-size: 0.2rem">缩放:</div> <div class="flex-1"> <el-slider :max="10" :min="0.5" :step="0.5" v-model="scale" @change="editMarker" ></el-slider> </div> </div> <div class="flex1"> <div style="width: 60px; font-size: 0.2rem">角度:</div> <div class="flex-1"> <el-slider :max="360" :step="5" v-model="rotate" @change="editMarker" ></el-slider> </div> </div> </div> <div class="w100 center mb-20"> <!-- <img src="./components/img/index5-btn1.png" alt="" style="width: 140px" @click="saveImg" class="pointer" v-if="isSave" /> --> <img src="./components/img/index5-btn3.png" alt="" style="width: 120px" @click="removeMarker" class="pointer" /> </div> </div> </div> </div> </div> </template> <script> import html2canvas from "html2canvas"; import "./components/js/flexible.js"; import { getPoliceDetailApi, uploadHtmlImg, dispatchHtmlImg, } from "./components/js/api"; import AMapLoader from "@amap/amap-jsapi-loader"; import icon1 from "./components/img/index5-1.png"; import icon2 from "./components/img/index5-2.png"; import icon3 from "./components/img/index5-3.png"; import icon4 from "./components/img/index5-4.png"; import icon5 from "./components/img/index5-5.png"; import icon6 from "./components/img/index5-6.png"; import icon7 from "./components/img/index5-7.png"; import icon8 from "./components/img/index5-8.png"; import icon9 from "./components/img/index5-9.png"; //秘钥 window._AMapSecurityConfig = { securityJsCode: "3e9a9aeb435372339552fc215f8d0918", }; export default { data() { return { position: [], policeId: "", map: null, showMenu: true, tab: [ { id: 1, icon: icon1, text: "消防车", }, { id: 2, icon: icon2, text: "消防员", }, { id: 3, icon: icon3, text: "水管", }, { id: 4, icon: icon4, text: "进攻方向", }, { id: 5, icon: icon5, text: "消防栓", }, { id: 6, icon: icon6, text: "危化品", }, { id: 7, icon: icon7, text: "风向", }, { id: 8, icon: icon8, text: "指北矢标", }, ], list: [], //地图上所有的marker draggingEnded: false, index: null, //当前拖动的索引-对应左侧菜单 showEdit: false, //是否显示编辑 item: {}, //当前编辑的marker // 编辑 scale: 1, //缩放 rotate: 0, //旋转角度 //保存 baseUrl: process.env.VUE_APP_BASE_API, isSave: false, }; }, mounted() { this.position = this.$route.query.position.split(","); this.policeId = this.$route.query.id; this.initAMap(); }, beforeDestroy() { this.map.destroy(); }, methods: { // -----------地图-------------- initAMap() { AMapLoader.load({ key: "130cca3be68a2ff0fd5ebb6de25e4eac", // 申请好的Web端开发者Key,首次调用 load 时必填 version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 plugins: [ // "AMap.ControlBar", // "AMap.ToolBar", // "AMap.Weather", // "AMap.CitySearch", // "AMap.Marker", // "AMap.MouseTool", // "AMap.PolyEditor", // "AMap.Polyline", // "AMap.Geolocation", // "AMap.GraspRoad", // "AMap.Geocoder", // "AMap.GeometryUtil.ringArea", // "AMap.DistrictSearch", // "AMap.MoveAnimation", "AMap.Driving", // 驾车路线路径规划 ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 }) .then((AMap) => { this.map = new AMap.Map("containerMap", { // 设置地图容器id // rotateEnable: true, // 旋转 // pitchEnable: true, // 倾斜 zoom: 13, // 初始化地图层级 // pitch: 50, // 倾斜角度 // rotation: -15, // 地图旋转角度 // viewMode: "3D", //开启3D视图,默认为关闭 zooms: [2, 20], // 设置地图显示范围 center: [119.419251, 32.400703], // 设置地图中心点 mapStyle: "amap://styles/blue", //设置地图的显示样式 WebGLParams: { preserveDrawingBuffer: true, // 使用html2canvas截取需要设置该属性,否则截取不到地图 }, }); this.map.on("complete", () => { console.log("地图加载完成"); this.isSave = true; this.createFireMarker(); //可以监听到拖动到地图 this.map.on("mouseover", this.onMouseOver); getPoliceDetailApi(this.policeId).then((res) => { if (res.data.screenshotParam) { this.list = JSON.parse(res.data.screenshotParam); this.showMarker(); } }); }); this.map.on("click", (e) => { // e 是事件对象,包含了点击的位置等信息 var lnglat = e.lnglat; // 获取经纬度坐标 console.log("地图被点击,坐标:" + lnglat.lng + ", " + lnglat.lat); this.showEdit = false; // 在此处可以进行进一步的操作,如弹出信息窗口、绘制标记等 }); }) .catch((e) => { console.log(e); }); }, //----------添加警情中心点标记 ------- createFireMarker() { var marker = new AMap.Marker({ position: new AMap.LngLat(...this.position), icon: new AMap.Icon({ image: fireIcon, imageSize: new AMap.Size(32, 42), }), // zIndex: 200, }); this.map.add(marker); // 设置地图中心点 this.map.setCenter(new AMap.LngLat(...this.position)); }, onDragStart(event) { // console.log("Drag start", event, event.target.dataset.index); //event.dataTransfer.setData( // "application/index", // event.target.dataset.index //); // 你还可以在这里做其他事情,比如改变元素的样式或状态 this.draggingEnded = false; this.index = event.target.dataset.index * 1; }, onDragEnd(event) { // console.log( // "Drag end", // event, // event.dataTransfer.getData("application/index") // ); //const data = event.dataTransfer.getData("application/index"); // 获取拖动时设置的数据 // console.log("接收到的数据:", data); // 拖拽结束时,你可以做一些清理工作,例如重置元素样式或状态 this.draggingEnded = true; }, onMouseOver(event) { // console.log("mouseover", event.lnglat); if (this.draggingEnded) { // 转换鼠标位置为地理坐标 this.draggingEnded = false; this.createMarker([event.lnglat.lng, event.lnglat.lat]); } }, // 页面一进来拿到上次的list渲染出来 showMarker() { this.list.forEach((item, index) => { item.show = true; item.marker = null; item.icon = [icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8][ item.id * 1 ]; var markerContent = '<div class="custom-content-marker" >' + '<img style="transform:rotate(' + item.rotate + "deg) scale(" + item.scale + ');width:60px;height:60px" src=" ' + item.icon + '">' + "</div>"; item.marker = new AMap.Marker({ position: new AMap.LngLat(...item.lnglat), content: markerContent, // 以 icon 的 [center bottom] 为原点 offset: new AMap.Pixel(-25, -50), // zIndex: 200, cursor: "move", draggable: true, }); this.map.add(item.marker); // 监听点点击事件 this.list[index].marker.on("click", (e) => { this.item = this.list[index]; this.scale = this.item.scale; this.rotate = this.item.rotate; this.showEdit = true; //拖动坐标获取新坐标 console.log("点击:", this.item.id); }); // 监听点拖动更新坐标 this.list[index].marker.on("dragend", (e) => { this.list[index].lnglat = [ this.list[index].marker.getPosition().lng, this.list[index].marker.getPosition().lat, ]; this.item = this.list[index]; this.scale = this.item.scale; this.rotate = this.item.rotate; this.showEdit = true; //拖动坐标获取新坐标 console.log( "最新坐标:", [ this.list[index].marker.getPosition().lng, this.list[index].marker.getPosition().lat, ], this.list, this.item ); }); }); console.log("createMarker", this.list); }, // 从左侧拖动过来新建点 createMarker(lnglat) { let length = this.list.length; this.list.push({ id: this.index, lnglat: lnglat, icon: this.tab[this.index].icon, marker: null, scale: 1, rotate: 0, show: true, }); this.item = this.list[length]; console.log("createMarker", this.index); var markerContent = '<div class="custom-content-marker" >' + '<img style="transform:rotate(' + this.item.rotate + "deg) scale(" + this.item.scale + ');width:60px;height:60px" src=" ' + this.item.icon + '">' + "</div>"; this.item.marker = new AMap.Marker({ position: new AMap.LngLat(...this.item.lnglat), content: markerContent, // 以 icon 的 [center bottom] 为原点 offset: new AMap.Pixel(-25, -50), // zIndex: 200, cursor: "move", draggable: true, }); this.map.add(this.item.marker); this.showEdit = true; this.scale = this.item.scale; this.rotate = this.item.rotate; console.log("createMarker", this.list, this.item); // 监听点点击事件 this.list[length].marker.on("click", (e) => { this.item = this.list[length]; this.scale = this.item.scale; this.rotate = this.item.rotate; this.showEdit = true; //拖动坐标获取新坐标 console.log("点击:", this.item.id); }); // 监听点拖动更新坐标 this.list[length].marker.on("dragend", (e) => { this.list[length].lnglat = [ this.list[length].marker.getPosition().lng, this.list[length].marker.getPosition().lat, ]; this.item = this.list[length]; this.scale = this.item.scale; this.rotate = this.item.rotate; this.showEdit = true; //拖动坐标获取新坐标 console.log( "最新坐标:", [ this.list[length].marker.getPosition().lng, this.list[length].marker.getPosition().lat, ], this.list, this.item ); }); }, // 编辑点重新渲染 editMarker() { var index = this.list.indexOf(this.item); console.log("编辑", this.rotate, this.scale, this.list[index]); this.list[index].scale = this.scale; this.list[index].rotate = this.rotate; this.map.remove(this.list[index].marker); this.list[index].marker = null; var markerContent = '<div class="custom-content-marker" >' + '<img style="transform:rotate(' + this.list[index].rotate + "deg) scale(" + this.list[index].scale + ');width:60px;height:60px" src=" ' + this.list[index].icon + '">' + "</div>"; console.log("编辑", markerContent); this.list[index].marker = new AMap.Marker({ position: new AMap.LngLat(...this.list[index].lnglat), content: markerContent, // 以 icon 的 [center bottom] 为原点 offset: new AMap.Pixel(-25, -50), // zIndex: 200, cursor: "move", draggable: true, }); this.map.add(this.list[index].marker); // 监听点点击事件 this.list[index].marker.on("click", (e) => { this.item = this.list[index]; this.scale = this.list[index].scale; this.rotate = this.list[index].rotate; this.showEdit = true; //拖动坐标获取新坐标 console.log("点击11:", this.item.id); }); // 监听点拖动更新坐标 this.list[index].marker.on("dragend", (e) => { this.item = this.list[index]; this.item.lnglat = [ this.list[index].marker.getPosition().lng, this.list[index].marker.getPosition().lat, ]; this.scale = this.list[index].scale; this.rotate = this.list[index].rotate; this.showEdit = true; }); }, // 删除点 removeMarker() { var index = this.list.indexOf(this.item); this.list[index].show = false; this.map.remove(this.list[index].marker); this.item = {}; this.showEdit = false; console.log("删除", this.list, this.item, index); }, /* -----------------------------下发作战--------------------- */ issueImg() { this.showMenu = false; let arr = this.list.filter((item) => item.show); let arr1 = arr.map((item) => { return { id: item.id, lnglat: item.lnglat, scale: item.scale, rotate: item.rotate, }; }); html2canvas(this.$refs.htmlImg, { useCORS: true, //保证跨域图片的显示,如果为不添加改属性,或者值为false,地图底图不显示 x: window.pageXOffset, //页面在水平方向的滚动距离 y: window.pageYOffset, //页面在垂直方向的滚动距离 }).then((canvas) => { var img = new Image(); var canvas2 = document.getElementById("myCanvas"); var ctx = canvas2.getContext("2d"); ctx.fillStyle = "#FFFFFF"; //画布填充色 ctx.lineWidth = "1"; ctx.rect(20, 30, canvas2.width - 40, canvas2.height - 60); //矩形距离画布左上角水平和垂直距离,矩形的宽高 ctx.stroke(); img.src = canvas.toDataURL(); var url = canvas.toDataURL("image/png"); const blobImage = this.dataURLtoBlob(url); let fileName = `htmlImg_${new Date().getTime()}.jpg`; const fileOfBlob = new File([blobImage], fileName); let formData = new FormData(); formData.append("file", fileOfBlob, fileName); this.isSave = false; uploadHtmlImg(formData).then((res) => { this.showMenu = true; this.isSave = true; // this.$modal.msgSuccess("上传成功"); let saveObj = { policeId: this.$route.query.id, // policeId: 196, fileName: res.fileName, url: res.url, screenshotParam: JSON.stringify(arr1), }; dispatchHtmlImg(saveObj).then((res) => { this.$modal.msgSuccess("标绘下发成功,可在小程序对应警情中查看"); }); console.log("http://192.168.0.19:12020" + res.url); // console.log(this.baseUrl + res.url); }); }); }, // 转成bolb对象 dataURLtoBlob(dataUrl) { let arr = dataUrl.split(","), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime, }); }, }, }; </script> <style scoped lang="scss"> @import "./components/css/rem.scss"; .index5 { .home { width: 50px; position: fixed; right: 20px; top: 20px; z-index: 9999; } .left { width: 280px; left: 0; top: 10%; .img-bg { width: 50px; height: 50px; margin: auto; } } .right { width: 360px; // height: 280px; right: 50px; bottom: 50px; .editBox { background: #0005495d; background-image: url("./components/img/index5-bg-1.png"); background-repeat: no-repeat; /* 防止重复平铺 */ background-position: center; /* 居中对齐 */ background-size: 100% 100%; /* 根据容器大小等比例缩放至最大尺寸 */ background-attachment: local; .editContent { // background-image: url("./components/img/index5-bg-2.png"); // background-repeat: no-repeat; /* 防止重复平铺 */ // background-position: center; /* 居中对齐 */ // background-size: 100% 100%; /* 根据容器大小等比例缩放至最大尺寸 */ // background-attachment: local; } } } ::v-deep .el-slider__runway { background-color: rgba(0, 255, 255, 0.253); } ::v-deep .el-slider__bar { background-color: aqua; } ::v-deep .el-slider__button { border: 2px solid aqua; } ::v-deep .amap-marker-label { background: rgba(0, 0, 0, 0); color: aqua; border: none; } ::v-deep .amap-icon { width: 50px !important; height: 50px !important; } .title { font-size: 0.2rem; font-weight: 700; text-shadow: 0px 3px 7px #006cbf; img { width: 0.4rem; height: 0.4rem; } } .carInfo { position: absolute; border-radius: 10px; border: 1px solid cyan; background: rgba(0, 50, 73, 0.8); // left: 120px; // top: 230px; // background: url("./components/img/car-bg.png") no-repeat center center; background-size: 100% 100%; padding: 16px 10px 14px 20px; ::v-deep .dv-water-pond-level text { font-size: 15px; font-weight: normal !important; color: #fff !important; } } } .main { height: 1600px; width: 100%; background: #d4edff; } .svg { border: 1px solid red; width: 100px; height: 100px; } </style>