vue2 在图片上打点 自定义图标、大小、颜色,可拖动放大缩小

该代码示例展示了在Vue项目中如何使用拖动事件在SVG点位上打点,结合@dragstart和@drop事件处理缩放、移动及点击图标显示弹出层功能。组件包括鼠标悬浮时显示信息,支持点击和拖动操作,适用于地图或平面图的设备标记。
摘要由CSDN通过智能技术生成

只用到img标签的平面图和svg标签的点位,我项目用的是拖动事件打点,vue的@dragstart 和@drop="ondrop"事件配合,点击的话你们自己修改接收事件的方式即可

20230609-150853

图示:

在这里插入图片描述

鼠标悬浮图标显示弹出层
在这里插入图片描述

子组件

<template>
  <div class="clickMap">
    <div
      ref="clickMap"
      @mousewheel="mousewheelImg"
      :style="{
        transform: 'scale(' + num + ')',
        position: 'relative',
        width: '100%',
        height: '100%',
      }"
      @mousedown="moveMouse"
      @click="getOffect"
    >
      <div v-for="(item, index) in pointPosition" :key="index">
        <svg-icon
          @click="iconClick(item)"
          slot="reference"
          v-if="item.iconUrl && !popover"
          :style="{
            position: 'absolute',
            left: item.leftName + 'px',
            top: item.topName + 'px',
            fontSize: item.fontSize + 'px',
            color: item.iconColor,
          }"
          :icon-class="item.iconUrl"
        />
        <el-popover
          :ref="'popoverSH' + item.id"
          v-else
          popper-class="popover"
          placement="right-start"
          width="200"
          trigger="hover"
        >
          <div>
            <el-row>
              <el-col> <span>设备名称:</span> {{ item.deviceName }}</el-col>
              <el-col> <span>设备编号:</span> {{ item.id }} </el-col>
              <el-col>
                <span>设备类型:</span> {{ item.deviceTypeName }}</el-col
              >

              <el-col
                ><span>安装位置:</span> {{ item.installationLocation }}</el-col
              >
              <el-col
                ><span>状态:</span>
                <b style="color: red" v-if="item.useStatus == 1">未激活</b
                ><b style="color: #0ecc67" v-if="item.useStatus == 2">在线</b
                ><b style="color: red" v-if="item.useStatus == 3"
                  >离线</b
                ></el-col
              >
              <p style="text-align: right">
                <span @click="detailEvent(item)" class="xiaoshou"
                  >详情<i class="el-icon-d-arrow-right"></i
                ></span>
              </p>
            </el-row>
          </div>
//svg-icon是ruoyi框架的组件,你们没有的自行替换
          <svg-icon
            slot="reference"
            v-if="item.iconUrl"
            :style="{
              position: 'absolute',
              left: item.leftName + 'px',
              top: item.topName + 'px',
              fontSize: item.fontSize + 'px',
              color: item.iconColor,
            }"
            :icon-class="item.iconUrl"
          />
        </el-popover>
      </div>

      <img
        style="width: 100%; height: 100%; pointer-events: none"
        :src="detailTable.url"
        alt=""
        @mousedown="isTrue ? null : move"
      />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: "",
      height: "",
      left: "",
      top: "",
      biaozhuHeight: 0,
      biaozhuWidth: 0,
      biaozhuTop: 0,
      biaozhuLeft: 0,
      moveTop: 0,
      moveLeft: 0,
    };
  },
  props: {
    detailTable: Object, //包含图片的对象
    isTrue: Boolean, //是否可以拖动
    pointPosition: Array, //点位坐标数组
    drag: Boolean,
    num: {
      //放大缩小倍速默认1
      type: Number,
      default: 1,
    },
    popover: {
      //是否显示弹出层
      type: Boolean,
      default: false,
    },
  },
  methods: {
    // 放大缩小
    mousewheelImg(e) {
      if (e.deltaY > 0) {
        if (this.num < 0.3) return;
        this.$emit("zoom", "缩小");
      } else {
        this.$emit("zoom", "放大");
      }
    },
    getOffect(e) {
      document.onmouseup = null;
    },
    // 拖动
    moveMouse(e) {
      let odiv = e.target; //获取目标元素

      //算出鼠标相对元素的位置
      let disX = e.clientX - odiv.offsetLeft;
      let disY = e.clientY - odiv.offsetTop;
      //   console.log(disX, disY);
      if (this.isTrue) {
        // 拖动
        document.onmousemove = (e) => {
          //鼠标按下并移动的事件
          //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
          let left = e.clientX - disX;
          let top = e.clientY - disY;
          //绑定元素位置到positionX和positionY上面
          this.positionX = top;
          this.positionY = left;
          //移动当前元素
          odiv.style.left = left + "px";
          odiv.style.top = top + "px";
        };
        document.onmouseup = (e) => {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      }
    },
    detailEvent(item) {
      this.$refs["popoverSH" + item.id][0].doClose(); //点击之后隐藏面板
      this.$emit("detailEvent", item);
    },
    // 打点事件
    ondrop(e) {
      let odiv = e.target; //获取目标元素

      //算出鼠标相对元素的位置
      let disX = e.clientX - odiv.offsetLeft;
      let disY = e.clientY - odiv.offsetTop;
      console.log(disX, disY);
      if (this.isTrue) {
        // 拖动
        document.onmousemove = (e) => {
          //鼠标按下并移动的事件
          //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
          let left = e.clientX - disX;
          let top = e.clientY - disY;
          //绑定元素位置到positionX和positionY上面
          this.positionX = top;
          this.positionY = left;
          //移动当前元素
          odiv.style.left = left + "px";
          odiv.style.top = top + "px";
        };
        document.onmouseup = (e) => {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      } else {
        let left =
          disX -
          odiv.getBoundingClientRect().x +
          Number(this.$refs.clickMap.style.left.replace(/px/, "") - 5);
        let top =
          disY -
          odiv.getBoundingClientRect().y +
          Number(this.$refs.clickMap.style.top.replace(/px/, "") - 5);

        let data = {
          leftName: left / this.num,
          topName: top / this.num,
          //   iconName: "sensor", //没有传图标的话默认传感器图标
        };
        this.$emit("addBitmap", data);

        this.biaozhuWidth = 0;
        this.biaozhuHeight = 0;
        this.biaozhuLeft = 0;
        this.biaozhuTop = 0;
        document.onmousemove = null;
        document.onmouseup = null;
      }
    },

    //点击图标事件
    iconClick(data) {
      this.$emit("iconClick", data);
    },
  },
  destroyed() {
    document.mousewheelImg = null;
  },
};
</script>

<style lang="scss">
.popover {
  background: #678295;
  border: 2px solid #0095ff;
  color: #ffffff;
  font-size: 16px;
  .xiaoshou {
    cursor: pointer; /*鼠标悬停变小手*/
  }
  .el-col {
    line-height: 32px;
    span {
      font-weight: bold;
    }
  }
}
.clickMap {
  width: 400px;
  height: 300px;
  //   background: red;
  margin: 0 auto;
  position: relative;
  // border: 1px solid #999999;

  .r_b {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 20px;
    height: 20px;
    // background: red;
  }
  .r_b:hover {
    cursor: se-resize;
  }
}
.popover-top {
  height: 60px;
  img {
    width: 50px;
    height: 50px;
  }
  span {
    float: right;
  }
}
.popover-content,
.popover-footer {
  border-top: 1px solid #f1f1f1;
  span {
    margin-right: 5px;
    font-weight: bold;
  }
  .el-col {
    line-height: 22px;
  }
}
</style>

父组件

<div class="maList" ref="maList" @dragover.prevent @drop="ondrop">
          <click-map
            @addBitmap="addBitmap"
            :detailTable="detailTable"
            :pointPosition="mapTable"
            :isTrue="isTrue"
            :num="num"
            @zoom="zoom"
            v-if="detailTable.url"
            :drag="true"
            ref="clickMap"
            @iconClick="iconClick"
          />
        </div>
data() {
    return {
     /*-mapTable: [[{leftName:11,topName:11,fontSize:11,iconColor:'#999999',iconUrl:图标的地址}]]---*/
      /*--detailTable里面要有url--*/
      /*--------------------------------*/
      detailTable: {}, //图片
      isTrue: true, //是否允许拖动
      checkedTable: {}, //保存拖动要打点设备的参数
      mapTable: [], //打点的坐标数组
      num: 1, //放大缩小倍数
      /*--------------------------------*/
 
    };
  },
  // 点击图标滚动到某一行事件
    iconClick(data) {
      this.radioType = 1;
      this.$nextTick(function () {
        this.deviceList.forEach((element, index) => {
          if (element.id == data.id) {
            console.log(index);
            //滚动到某一行加高亮
            this.$refs.deviceList.scrollToRow(this.deviceList[index]);
            this.$refs.deviceList.setCurrentRow(this.deviceList[index]);
          }
        });
      });
    },
    // 打点之后返回的坐标系数
    addBitmap(data) {
      this.checkedTable.spaceId = this.$refs.tree.getCurrentNode().id;
      this.checkedTable.topName = data.topName;
      this.checkedTable.leftName = data.leftName;

      console.log(this.checkedTable);
      uploadDevice(this.checkedTable).then((res) => {
        this.isTrue = !this.isTrue;
        this.$message({
          message: "打点成功",
          type: "success",
        });
        this.getDevice(); //更新设备列表
        this.equipmentOverviewEvent() //更新设备总览
        deviceList(this.mapForm).then((res) => {
          this.mapTable = res.rows;
          this.total = res.total;
        });
      });
    },
    // 放大缩小
    zoom(value) {
      if (value == "放大") {
        this.num += 0.1;
      } else {
        this.num -= 0.1;
      }
    },
    dragstart(data) {
      this.checkedTable = data;
      this.isTrue = false;
      console.log("长按拖动中");
    },
    ondrop(e) {
      console.log("长按松开了");
      this.$refs.clickMap.ondrop(e);
    },

在这里插入图片描述

公司需要拖动打点,dragstart和ondrop方法就是vue的拖动松开配合使用的事件,不懂的可以自行百度,可以简单的改为点击打点也行,自行修改

后续更新一点小demo给你们参考

20230627-171901

源码下载地址:
https://gitee.com/coderjiejie/vue2_map

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Vue2中使用Hammer.js实现移动端div的拖拽、放大缩小和旋转可以按照以下步骤进行。 首先,在Vue项目中安装Hammer.js。 ``` npm install hammerjs ``` 然后,在需要使用拖拽、放大缩小和旋转功能的组件中引入Hammer.js,并初始化一个Hammer实例,将其绑定到要拖拽、放大缩小和旋转的div元素上。 ``` import Hammer from 'hammerjs' export default { mounted() { const element = this.$refs.element // 获取div元素的引用 const mc = new Hammer.Manager(element) // 初始化Hammer实例并将其绑定到div元素上 // 添加拖拽、放大缩小和旋转的手势识别 mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 })) mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith(mc.get('pan')) mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan')) // 初始化div元素的拖拽、放大缩小和旋转的初始状态值 let posX = 0 let posY = 0 let scale = 1 let lastScale = 1 let rotation = 0 // 监听拖拽事件 mc.on('pan', (e) => { // 实现拖拽 posX = e.deltaX posY = e.deltaY element.style.transform = `translate(${posX}px, ${posY}px) scale(${scale}) rotate(${rotation}deg)` }) // 监听放大缩小事件 mc.on('pinch', (e) => { // 实现放大缩小 scale = lastScale * e.scale element.style.transform = `translate(${posX}px, ${posY}px) scale(${scale}) rotate(${rotation}deg)` }) // 监听旋转事件 mc.on('rotate', (e) => { // 实现旋转 rotation = e.rotation element.style.transform = `translate(${posX}px, ${posY}px) scale(${scale}) rotate(${rotation}deg)` }) } } ``` 最后,在该组件的模板中添加一个div元素,并给其添加初始样式。 ``` <template> <div ref="element" style="width: 200px; height: 200px; background-color: red;"></div> </template> ``` 这样,当你在移动端上访问这个页面时,就可以拖拽、放大缩小和旋转这个div元素了。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值