美文网首页
vue中拖动元素效果实现,以及拖拽`缩放后的元素`效果实现

vue中拖动元素效果实现,以及拖拽`缩放后的元素`效果实现

作者: lazy_tomato | 来源:发表于2020-11-24 22:32 被阅读0次

START

  • 番茄我又又又来写点啥了,最近被需求折磨的不要不要的,要做一个在线PPT做的网站。元素拖动算是其中一小部分的功能吧,但是还是出了很多的bug,这篇文章算是我对元素拖拽相关的记录吧。
  • 仅以此文记录自己寻找问题花费的3小时。

元素拖动

  • 话不多说先上代码,后面再一个一个解释
<template>
  <div class="move">
    <h2>vue中元素拖动一</h2>
    <div class="all">
      <div
        class="item"
        @mousedown.stop="move($event)"
        :style="{ left: sonLeft+'px', top: sonTop+'px' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sonLeft: 10,
      sonTop: 20,
    };
  },
  methods: {
    // 元素拖动事件
    move(e) {
      let element = e.currentTarget;

      //算出鼠标相对元素的位置
      let disX = e.clientX - element.offsetLeft;
      let disY = e.clientY - element.offsetTop;

      document.onmousemove = (e) => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        let left = e.clientX - disX;
        let top = e.clientY - disY;
          
        //移动当前元素
        this.sonLeft = left;
        this.sonTop = top;
      };
      document.onmouseup = (e) => {
        //鼠标弹起来的时候不再移动
        document.onmousemove = null;
        //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
        document.onmouseup = null;
      };
    },
  },
};
</script>

<style scoped>
.all {
  position: relative;
  width: 1000px;
  height: 700px;
  background-color: pink;
}

.item {
  position: absolute;
  left: 10px;
  top: 20px;
  width: 100px;
  height: 100px;
  background-color: yellow;
}
</style>

  • 简单说一下逻辑,给需要拖动的元素绑定left,top属性
  • 给需要拖动的元素绑定事件,根据鼠标的移动,修改对应元素的left,top变量
  • 难点就是 e.clientX ;e.clientY ;element.offsetTop;element.offsetLeft;这几个属性指的是什么,为什么这样就可以实现元素的拖动,画个图,很好理解,请看下图
位置计算_lazy_tomato.jpg
  • 如果上图不好理解,简单的说就是 鼠标相对于之前挪动了 SS加上元素原本的偏移量,就是元素挪动之后的偏移量。

若上一级定位元素缩放了怎么做拖拽

  • 由于是在线ppt的需求,所以定位元素的大小是自适应的,会发生缩放,所以对应的left,top要响应的改变
  • 话不多说直接上代码
<template>
  <div class="move">
    <h2>vue中元素拖动二</h2>
    <div class="all">
      <div
        class="item"
        @mousedown.stop="move($event)"
        :style="{ left: sonLeft + 'px', top: sonTop + 'px' }"
      >
        left: {{ sonLeft }}
        <br />
        top{{ sonTop }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sonLeft: 20,
      sonTop: 10,
    };
  },
  methods: {
    // 元素拖动事件
    move(e) {
      let element = e.currentTarget;
        
      //算出鼠标相对元素的位置
      let disX = e.clientX - element.offsetLeft * 0.6;
      let disY = e.clientY - element.offsetTop * 0.6;


      document.onmousemove = (e) => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        //移动当前元素

        this.sonLeft = left / 0.6;
        this.sonTop = top / 0.6;
      };
      document.onmouseup = (e) => {
        //鼠标弹起来的时候不再移动
        document.onmousemove = null;
        //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
        document.onmouseup = null;
      };
    },
  },
};
</script>

<style scoped>
.all {
  position: relative;
  width: 1000px;
  height: 700px;
  background-color: pink;
  transform: scale(0.6, 0.6);
  transform-origin: 0% 0%;
}

.item {
  position: absolute;
  left: 10px;
  top: 20px;
  width: 100px;
  height: 100px;
  background-color: yellow;
}
</style>

啰嗦一句,上述代码的0.6就是缩放比例,由于比较懒,没有改,应该是用变量去控制相对来说好很多。

至于怎么在vue中变量绑定transform: scale(0.6, 0.6);看下面的链接文章

vue中变量绑定transform: scale()

还未解决的问题

  • 先上代码
<template>
  <div class="move">
    <h2 @click="add">vue中元素拖动三</h2>

    <div class="all">
      <div
        class="item"
        v-for="(item, index) in list"
        :key="item.name"
        :style="{ left: item.sleft + 'px', top: item.stop + 'px' }"
        @mousedown.stop="move(index, $event)"
      >
        <img :src="item.url" alt="" style="width: 100%; height: 100%" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sonLeft: 0,
      sonTop: 0,
      list: [
        {
          name: "1",
          sleft: 20,
          stop: 30,
          url:
            "https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
        },
        {
          name: "2",
          sleft: 200,
          stop: 300,
          url:
            "https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
        },
        {
          name: "3",
          sleft: 400,
          stop: 600,
          url:
            "https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
        },
      ],
    };
  },
  methods: {
    // 元素拖动事件
    move(index, e) {
      let element = e.currentTarget;
      console.log(e.currentTarget);
      //   阻止默认的图片拖拽事件
      e.preventDefault();

      //算出鼠标相对元素的位置
      let disX = e.clientX - element.offsetLeft * 0.6;
      let disY = e.clientY - element.offsetTop * 0.6;

      document.onmousemove = (e) => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        //移动当前元素

        this.list[index]["sleft"] = left / 0.6;
        this.list[index]["stop"] = top / 0.6;

      };
      document.onmouseup = (e) => {
        //鼠标弹起来的时候不再移动
        document.onmousemove = null;
        //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)
        document.onmouseup = null;
      };
    },

    add() {
      console.log("添加元素");
      this.list.push({
        name: "4",
        url:
          "https://upload.jianshu.io/users/upload_avatars/13278218/60803b63-0f9d-490e-9c41-1511c56025d4?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
      });
    },
  },
};
</script>

<style scoped>
.all {
  position: relative;
  width: 1000px;
  height: 1000px;
  background-color: pink;
  transform: scale(0.6, 0.6);
  transform-origin: 0% 0%;
}

.item {
  position: absolute;
  left: 0px;
  top: 0px;
  width: 100px;
  height: 100px;
  background-color: yellow;
}
</style>

描述

  • 我写了一个demo
  • vue下 一个图片列表
  • 然后绑定变量到样式的top left 实现位置的控制
  • 添加一个点击事件 然后往展示的list数组里面添加一个对象
  • 但是这个对象没有加 top left 属性(原本list中的对象都有这两个属性)
  • 然后给这些图片列表添加了元素拖动的事件
  • 数组中有left top属性的元素拖拽 很流畅
  • 但是新添加的对象,因为没有 加left top 拖动特别卡顿
  • 还不清楚原因。。能解决的私聊我,发红包

END

整体的元素拖拽其实理解清楚对应的属性,理解计算的方法很好理解的,整体来说不难,后面的问题,暂时能力有限,先记录一下吧。后期能解决了,定会补充。时间匆忙,命名不规范见谅。

相关文章

网友评论

      本文标题:vue中拖动元素效果实现,以及拖拽`缩放后的元素`效果实现

      本文链接:https://www.haomeiwen.com/subject/saowiktx.html