vue3 vue2 移动图标标点组件

12 篇文章 0 订阅
2 篇文章 0 订阅

vue3

安装vue-draggable-resizable
详细信息:https://blog.csdn.net/yrqlyq/article/details/124843770
组件

<script lang="ts" setup>
import VueDraggableResizable from "vue3-draggable-resizable"
// import "vue3-draggable-resizable/dist/Vue3DraggableResizable.css"
import { ref, watchEffect } from "vue"
const draggingId = ref()
const emit = defineEmits(["tungInfo"])
const props = defineProps({
  imgUrl: {
    type: String,
    default: ""
  },
  // 图标数组
  list: {
    type: Array,
    default: () => []
  },
  // 组件对应字段
  objName: {
    type: Object,
    default: () => {}
  }
})
const dragStart = (id: number | string) => {
  draggingId.value = id
  console.log("draggingId", draggingId.value)
}
const onDragEnd = (e: { x: number; y: number }) => {
  const item = props.list.find(
    (i: any) => i[props.objName.id] === draggingId.value
  )

  item[props.objName.x] = e.x
  item[props.objName.y] = e.y
  emit("tungInfo", item)
}
</script>
<template>
  <div>
    <div
      class="bg-img"
      :style="'background:url(' + imgUrl + ');backgroundSize:100% 100%'"
    >
      <VueDraggableResizable
        v-for="item in list"
        :key="item[objName.id]"
        :onDragStart="() => dragStart(item[objName.id])"
        :x="item[objName.x]"
        :y="item[objName.y]"
        :w="40"
        :h="30"
        :resizable="false"
        :parent="true"
        @drag-end="onDragEnd"
      >
        <div class="icon">{{ item[objName.name] }}</div>
      </VueDraggableResizable>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.bg-img {
  width: 800px;
  height: 500px;
  position: relative;
  .icon {
    display: inline-block;
    padding: 5px 15px;
    border-radius: 5px;
    background: #1381f3;
    color: #fff;
    position: relative;
    &::after {
      content: "";
      border-left: 6px solid transparent;
      border-right: 6px solid transparent;
      border-bottom: 8px solid #1381f3;
      position: absolute;
      top: 33px;
      left: 23px;
      transform: rotate(180deg);
    }
  }
}
.vdr-container .dragging {
  border-color: transparent !important;
}
:deep(.vdr-container .dragging) {
  border-color: transparent !important;
}
:deep(.vdr-container.active) {
  border-color: transparent !important;
}
</style>

例子

<script setup lang="ts">
import { reactive, onMounted } from "vue"
import MapIcon from "./HotspotMap.vue"
const state = reactive({
  imgUrl:
    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fstatic.loupan.com%2Fupfile2%2Fimage%2F20170315%2F20170315131312_8211318.jpg&refer=http%3A%2F%2Fstatic.loupan.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663741900&t=71252557b8aace751a4d2963974a26e8",
  list: [
    { mapId: 1, name: 15, mapX: 200, mapY: 200 },
    { mapId: 2, name: 5, mapX: 100, mapY: 100 },
    { mapId: 3, name: 8, mapX: 680, mapY: 370 },
    { mapId: 4, name: 7, mapX: 36, mapY: 190 },
    { mapId: 5, name: 10, mapX: 63, mapY: 45 }
  ],
  subrr: [],
  objName: {}
})
state.objName = {
  id: "mapId",
  name: "name",
  x: "mapX",
  y: "mapY"
}
const tungInfo = (e: any) => {
  console.log(e, state.list)
}
</script>
<template>
  <div class="content-manage">
    <div class="button">
      <el-button @click="addEditClick(1, {})">新增</el-button>
    </div>
    <MapIcon
      :imgUrl="state.imgUrl"
      :list="state.list"
      @tungInfo="tungInfo"
      :objName="state.objName"
    />
  </div>
</template>

vue2

<template>
  <div>
    <div class="bg-img" :style="'background:url('+imgUrl+');backgroundSize:100% 100%'">
      <VueDraggableResizable 
        v-for="item in list" 
        :key="item[objName.id]" 
        :onDragStart="() => dragStart(item[objName.id])"
        :x ="item[objName.x]" 
        :y ="item[objName.y]" 
        :w ="40" 
        :h ="30" 
        :parent="true" 
        @dragstop ="onDragstop"
      >
        <div class="icon">{{item[objName.name]}}</div>
      </VueDraggableResizable>
    </div>
  </div>
</template>
<script>
import VueDraggableResizable from 'vue-draggable-resizable'
export default({
  components: {
    VueDraggableResizable
  },
  props: {
    imgUrl: {
      type: String,
      default: ''
    },
    // 图标数组
    list: {
      type: Array,
      default: () => []
    },
    // 组件对应字段
    objName: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      draggingId: 0
    }
  },
  methods: {
    dragStart(id) {
      this.draggingId = id
    },
    onDragstop(x, y) {
      const item = this.list.find((i) => i[this.objName.id] === this.draggingId)
      console.log(this.list, item)
      item[this.objName.x] = x
      item[this.objName.y] = y
      this.$emit('tungInfo', item)
    }
  }
})
</script>
<style lang="scss" scoped>
.bg-img{
  width: 800px;
  height: 500px;
  display: flex;
  .icon{
    display: inline-block;
    padding: 5px 15px;
    border-radius: 5px;
    background: #1381f3;
    color: #fff;
    position: relative;
    &::after{
      content: '';
      border-left: 6px solid transparent;
      border-right: 6px solid transparent;
      border-bottom: 8px solid #1381f3;
      position: absolute;
      top: 27px;
      left: 23px;
      transform: rotate(180deg);
    }
  }
}

</style>

例子

<template>
  <div>
    图标拖动
    <MapIcon :imgUrl='imgUrl' :list='list' @tungInfo='tungInfo' :objName='objName'/>
  </div>
</template>
<script>
import MapIcon from './mapIcon.vue'
export default({
  components: {
    MapIcon
  },
  data() {
    return {
      imgUrl: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fstatic.loupan.com%2Fupfile2%2Fimage%2F20170315%2F20170315131312_8211318.jpg&refer=http%3A%2F%2Fstatic.loupan.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663741900&t=71252557b8aace751a4d2963974a26e8',
      list: [
        { mapId: 1, name: 15, mapX: 200, mapY: 200 },
        { mapId: 2, name: 5, mapX: 100, mapY: 100 },
        { mapId: 3, name: 8, mapX: 20, mapY: 200 },
        { mapId: 4, name: 7, mapX: 36, mapY: 190 },
        { mapId: 5, name: 10, mapX: 63, mapY: 45 }
      ],
      subrr: [],
      objName: {}
    }
  },
  created() {
    this.objName = {
      id: 'mapId',
      name: 'name',
      x: 'mapX',
      y: 'mapY'
    }
  },
  methods: {
    tungInfo(e) {
      console.log(e, this.list)
    }
  }
})
</script>

注:父页面需要position: relative;这样小图标才会定位在父页面上
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值