vue类似<area>热点区域

在这里插入图片描述

<template>
  <el-dialog :visible.sync="show" width="1000px" title="设备分布设置">
    <section class="btns">
      <div class="upload">
        <input type="file" @change="upload">
        上传图片
      </div>
      <el-button type="success" size="small" @click="send">提交设置</el-button>
      <el-button type="danger" size="small" @click="markers = []">清除设置</el-button>
    </section>
    <section class="content">
      <div class="imgBox">
        <el-tooltip placement="top" v-for="(item, key) in markers" :key=key>
          <div slot="content" class="tips">{{item.deviceName}}<i class="el-icon-circle-close" @click="remove(key)"></i>
          </div>
          <i class="marker" @mousedown="move($event, key)" :style="{left: item.left, top: item.top}">{{key + 1}}
          </i>
        </el-tooltip>
        <img :src="`${url}file/download/${imageId}`" alt="" @load="imgload" ref="img" draggable="false" v-if="imageId">
      </div>
      <div class="list">
        <header>选择设备</header>
        <div v-for="(item, key) in list" :key=key class="item">
          <span>{{item.deviceName}}</span> <i class="el-icon-circle-plus" @click="add(item, key)"></i>
        </div>
      </div>
    </section>
  </el-dialog>
</template>
<script>
  import common from '@/api/common'
  import device from '@/api/device/device'
  import monitorPoint from '@/api/monitor/monitorPoint'


  export default {
    name: 'deviceSet',
    data() {
      return {
        url: process.env.VUE_APP_BASE_API,
        monitorPointId: '',
        imageId: '',
        show: false,
        list: [],
        markers: [],
        height: 0
      }
    },
    created() { },
    methods: {
      init(data = {}) {
        this.list = []
        this.markers = []
        this.imageId = ''
        this.monitorPointId = data.id
        monitorPoint.getAssignPic(this.monitorPointId).then(({ flag, object }) => {
          if (flag == '0') {
            this.imageId = object.id
          }
        })
        device.getList({
          monitorPointId: this.monitorPointId
        }).then(res => {
          res.forEach(item => {
            if (item.leftPos || item.topPos) {
              this.markers.push({
                id: item.id,
                deviceName: item.deviceName,
                left: item.leftPos + '%',
                top: item.topPos + '%',
              })
            } else {
              this.list.push({
                id: item.id,
                deviceName: item.deviceName
              })
            }
          })
        })
        this.show = true
      },
      imgload() {
        this.height = this.$refs.img.height
      },
      upload(e) {
        const files = e.target.files
        let param = new FormData()
        param.append('file', files[0])
        common.upload(param).then(({ flag, object, msg }) => {
          if (flag == 0) {
            this.imageId = object[0].id
          }
        })
        e.target.value = null
      },
      send() {
        if (!this.imageId) {
          this.$fns.error('请先上传图片!')
          return;
        }
        if (this.markers.length == 0) {
          this.$fns.error('请先设置一个设备!')
          return;
        }
        const data = this.markers.map(item => {
          return {
            id: item.id,
            leftPos: item.positon ? item.positon.left : item.left.slice(0, -1) * 1,
            topPos: item.positon ? item.positon.top : item.top.slice(0, -1) * 1
          }
        })
        const load = this.$fns.loading()
        device.savePos({
          monitorPointId: this.monitorPointId,
          assignPic: this.imageId,
          posList: data
        }).then(({ flag, msg }) => {
          load.close()
          if (flag == 0) {
            this.$fns.success(msg, false)
            this.show = false
          }
        })
      },
      add(item, i) {
        if (!this.imageId) {
          this.$fns.error('请先上传图片')
          return;
        }
        this.list.splice(i, 1)
        this.markers.push({
          id: item.id,
          deviceName: item.deviceName,
          left: 0,
          top: 0
        })
      },
      remove(i) {
        this.list.push(this.markers[i])
        this.markers.splice(i, 1)
      },
      move(e, i) {
        const self = this
        let odiv = e.target;
        let disX = e.clientX - odiv.offsetLeft
        let disY = e.clientY - odiv.offsetTop
        document.onmousemove = (e) => {
          let left = e.clientX - disX;
          let top = e.clientY - disY;
          self.markers[i].left = left + 'px'
          self.markers[i].top = top + 'px'
          self.markers[i].positon = {
            top: top / self.height * 100,
            left: left / 7.2,
          }
        }
        document.onmouseup = (e) => {
          document.onmousemove = null
          document.onmouseup = null
        }
      }
    }
  }
</script>
<style lang="scss" scoped>
  section.btns {
    display: flex;
    align-items: center;
  }

  .upload {
    margin-right: 10px;
    font-size: 12px;
    border-radius: 3px;
    color: #fff;
    background-color: #409eff;
    border-color: #409eff;
    height: 32px;
    width: 80px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    overflow: hidden;

    &:hover {
      background: #66b1ff;
      border-color: #66b1ff;
      color: #fff;
    }

    input {
      cursor: pointer;
      position: absolute;
      left: 0;
      top: 0;
      opacity: 0;
      width: 100%;
      height: 100%;
    }
  }

  .content {
    margin-top: 15px;
    display: flex;

    .imgBox {
      width: 720px;
      position: relative;

      img {
        width: 100%;
        pointer-events: none;
      }

      .marker {
        position: absolute;
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 20px;
        height: 20px;
        background-color: #f00;
        border-radius: 50px;
        cursor: pointer;
        outline: none;
        border: 2px solid #fff;
        color: #fff;
        font-weight: bold;
      }
    }

    .list {
      flex: 1;
      margin-left: 10px;
      border: 1px solid #ebeef5;
      display: flex;
      flex-direction: column;

      header {
        background-color: #f9f9f9;
        padding: 10px;
        line-height: 22px;
        color: #909399;
        font-weight: bold;
        border-bottom: 1px solid #ebeef5;
      }

      .item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 42px;
        padding: 0 8px;
        border-bottom: 1px solid #ebeef5;

        i {
          cursor: pointer;
        }
      }
    }
  }
</style>

img的数据格式
在这里插入图片描述
右侧list的数据格式;
根据 leftPos 和 topPos , 计算 红色标记在图片上的位置
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值