美文网首页
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