• vue 中基于html5 drag drap的拖放


      事情是这样的,右边有各种控件,可以拖动到右边自由区,在自由区内可以随意拖动。

    案例一:

    开始的我,so easy! 通过绑定元素的mousedown 事件,监听鼠标的mousemove,和mouseup 事件,于是我轻松实现了同一区域内元素可以拖着跑,上代码!

    move (e) {
          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
            // 移动当前元素
            odiv.style.left = left + 'px'
            odiv.style.top = top + 'px'
          }
          document.onmouseup = e => {
            document.onmousemove = null
            document.onmouseup = null
          }
        }
    

      注意一点,被拖拽对象区域要设置position:relative, 否则的元素会自己抖动。

    以上代码并不能满足需要,要左右布局,左边的拖到右边,在右边区域随便拖动。

    案例二:

    好吧,首先我来布个局,左右布局,给元素绑定事件,上代码!

    <template>
      <div style='position: relative;'>
        <el-container>
          <el-aside width="300px">
            <ul>
              <li class='liStyle' v-for="item in tags" :key='item.id'><img src="../assets/timg.png" class='msg' alt="" @dragstart="dragstart" draggable="true" @drag='draging' @dragend="dragend"></li>
            </ul>
          </el-aside>
          <!-- 自由移动区域 -->
          <el-main>
            <div @drop="drop" @dragover.prevent style='height:600px;800px;'>
    
            </div>
            <!-- <svg id="svgDrag" width="1200" height="1000"></svg> -->
          </el-main>
        </el-container>
      </div>
    </template>

    事件绑定方法:

    dragstart (ev) {
          console.log('dragstart拖拽开始事件,绑定于被拖拽元素上', event)
          ev.dataTransfer.setData('Text', ev.target.id)
          this.offsetX = ev.offsetX
          this.offsetY = ev.offsetY
          console.log(this.offsetX + '-' + this.offsetY)
        },
        draging (e) {
          // console.log('拖动中')
          var x = e.clientX
          var y = e.clientY
          // console.log('shubiao client')
          if (x > 300) {
            console.log(this.tags)
            // drag事件最后一刻,无法读取鼠标的坐标,pageX和pageY都变为0
            if (x === 0 && y === 0) {
              return // 不处理拖动最后一刻X和Y都为0的情形
            }
            x -= this.offsetX
            y -= this.offsetY
            // console.log('e left')
            // console.log(x + '-' + y)
            /* 它的父级第一个存在定位的元素,如果有margin减去margin值  */
            e.target.style.left = x - 5 + 'px'
            e.target.style.top = y - 60 + 'px'
          }
        },
        drop (ev) {
          console.log('drop拖放事件,绑定可拖放区域', event)
          this.text = ev.dataTransfer.getData('Text')
          console.log(this.text)
          let target = document.getElementById(this.text)
          ev.target.appendChild(target)
          ev.preventDefault()
        },
        dragend (event) {
          event.dataTransfer.clearData()
        }
    

      如果不出意外的话,以上代码已经成功实现了元素从左边拖到右边。但是,右边元素被拖走了,右边就没有了,然后我尝试了各种,拖动开始时clone 元素,drap时clone元素等等,都不太完美。此时的我,崩溃……

    终于,也不知道哪来的灵感,这个困扰我两秒的难题突然就被我成功攻克了。好了,我要开始吹牛了……

      案例三:

           我的思路是这样的(不想看?直接看代码好了,反正是给我自己看的):左边列表元素可拖动(draggable='true'),绑定dragstart(开始事件),不要给它绑定draging(拖动事件),这样左边列表元素有拖动属性,但是位置不会改变。当右侧拖动区域

    第一次触发了drop 操作后,新生成一个对象,这个对象既有拖动(draggable='true')属性,也绑定dragstart(开始事件),拖动事件(drag),这样新元素会在右侧随意拖动。那么怎么新生成一个元素呢?自然不是appendChild 之类的,利用Vue 双向绑定的特性,

    页面上循环数组元素,生成元素即往数组中push 元素即可。每次拖动元素都会触发drop 事件,并不是每次都要生成一个新元素,要知道是从左边列表拖到右侧第一次drop 的时候生成新元素。怎么知道呢?这就是两个dragstart的妙处

    <t<template>
      <div style='position: relative;'>
        <el-container>
          <el-aside width="300px">
            <ul>
              <li class='liStyle' v-for="item in tags" :key='item.id'>
                <img src="../assets/timg.png" class='msg' alt="" @dragstart="dragstart" draggable="true" :id='item.id' @dragend="imgEnd">
              </li>
            </ul>
          </el-aside>
          <el-main>
            <div @drop.prevent="drop" @dragover.prevent style='height:1000px;1800px;'>
              <img src="../assets/timg.png" class='msg' :style="{left:item.x+'px',top:item.y+'px'}" alt="" v-for="(item, $index) in InfoList" :key='$index' @dragstart="imgStart" draggable="true" @drag='draging($event,item)' @dragend="imgEnd">
            </div>
          </el-main>
        </el-container>
      </div>
    </template>
    

      

      methods: {
        dragstart (ev) {
          let info = { id: ev.target.id, isDrop: true }
          ev.dataTransfer.setData('Text', JSON.stringify(info))
          this.offsetX = ev.offsetX
          this.offsetY = ev.offsetY
        },
        drop (e) {
          let info = JSON.parse(e.dataTransfer.getData('Text'))
          /* 判断是否是第一次进入拖拽区域,如果是第一次需要新生成对象,否则不需要 */
          if (info.isDrop) {
            var x = e.clientX
            var y = e.clientY
            x -= this.offsetX
            y -= this.offsetY
            info.x = x - 5
            info.y = y - 60
            info.id = info.id + Date.parse(new Date())
            this.InfoList.push(info)
          }
        },
        imgStart (e) {
          let info = { isDrop: false }
          e.dataTransfer.setData('Text', JSON.stringify(info))
          this.imgOffsetX = e.offsetX
          this.imgOffsetY = e.offsetY
        },
        draging (e, item) {
          item.x = e.clientX - this.imgOffsetX - 5
          item.y = e.clientY - this.imgOffsetY - 60
        },
        imgEnd (event) {
          console.log('done')
          console.log(event)
          event.dataTransfer.clearData()
        }
      }
    

      注意:拖动元素设置position:absolute属性

     最后,希望大家有哪些好的拖放插件,可以分享一下,基于jquery 的拖拽插件,我用过几个,但是总觉得vue中用jq有点怪。

  • 相关阅读:
    mongodb
    python中读取文件的read、readline、readlines方法区别
    uva 129 Krypton Factor
    hdu 4734
    hdu 5182 PM2.5
    hdu 5179 beautiful number
    hdu 5178 pairs
    hdu 5176 The Experience of Love
    hdu 5175 Misaki's Kiss again
    hdu 5174 Ferries Wheel
  • 原文地址:https://www.cnblogs.com/caolidan/p/9887893.html
Copyright © 2020-2023  润新知