高德地图——态势标绘,创建点、移动位置、缩放、旋转、保存、删除

image.png

  • 拖动左侧图标到地图上某个位置,在地图上创建该类型的点,存储在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>

在Cesium中,先将需要标绘的物体或要素添加到Cesium的场景中。然后,可以使用Cesium提供的保存功能将标绘后的场景或视图保存为文件。 保存Cesium态势标绘可以有多种方式,其中一种常见的方式是将标绘保存为CZML(Cesium Language)文件格式。CZML是一种用来描述Cesium场景的JSON格式,包含了标绘要素的位置、形状、样式等信息。 保存Cesium态势标绘为CZML文件,可以使用Cesium提供的CZMLWriter类。首先,创建一个CZMLWriter实例,然后通过调用其方法将标绘要素的信息添加到CZMLWriter中。例如,可以使用Cesium的Entity API创建一个实体对象,设置该实体对象的位置、形状和样式等属性,并将其添加到CZMLWriter中。之后,通过调用CZMLWriter的write方法生成CZML文件。 另一种保存方式是将Cesium场景保存为图片文件,这可以通过调用Cesium的Scene类中的canvas对象的toDataURL方法来实现。该方法将场景中的所有内容渲染到一个HTML5 Canvas元素上,并返回数据URL,可以将数据URL作为图片文件进行保存。 此外,还可以使用Cesium提供的其他保存方式,比如保存为KML(Keyhole Markup Language)文件格式,这种格式在一些地理信息系统中也被广泛使用。 综上所述,Cesium态势标绘后可以通过保存为CZML文件、保存为图片文件或保存为其他格式的文件来进行保存。不同的保存方式可以根据实际需求选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小曲曲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值