美文网首页前端
HTML5拖拽事件

HTML5拖拽事件

作者: 心存美好 | 来源:发表于2022-05-13 10:17 被阅读0次

    HTML5拖拽事件

    1. 设置拖拽

    图片自带拖拽功能
    其他元素可设置draggable属性

    <div draggable="true">
        
    </div>
    
    <style>
        #box {
          position: fixed;
          top: 0;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
      </style>
    </head>
    
    <body>
      <div draggable="true" id="box"></div> <!-- draggable给div设置拖拽,希望是ture必须明确写上true -->
    </body>
    

    例子:

    box.ondragend = function (e) {
        box.style.cssText = 'top:' + (e.clientY) + 'px;left:' + (e.clientX) + 'px'
    
    }
    
      <style>
        #box {
          position: fixed;
          top: 0;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
      </style>
    </head>
    
    <body>
      <div draggable="true" id="box"></div> <!-- draggable实现拖拽功能,希望是ture必须明确写上true -->
    
    <script>
      //js实现元素拖到那儿就定位到哪
      box.ondragend = function (e) {  //ondragend是js拖拽事件,松开鼠标哪一刻就会触发这个事件,获取事件对象,获得元素距离浏览器左侧、顶端的距离
        // this.style.top =`${e.clientY}px`//这种写法实际是将鼠标所在点的值给了元素距离左侧和上部,不准确
        // this.style.left =`${e.clientX}px`
        // box.style.cssText = 'top:' + (e.clientY) + 'px;left:'+(e.clientX)+'px'//js中设置css样式的文本
        this.style.cssText = `top:${e.clientY}px;left:${e.clientX}px`//js中设置css样式的文本
      }
    </script>
    </body>
    
    1.1. 拖拽元素(被拖拽元素对象)事件 :
    1. ondragstart : 拖拽前触发 ,事件只触发一次
    2. ondrag :拖拽前、拖拽结束之间,连续触发
    3. ondragend :拖拽结束触发 ,事件只触发一次
    const box = document.getElementById('box');
    
    // dragstart 拖拽开始时触发,只触发一次
    box.ondragstart = function () {
        this.style.background = 'blue';
    
    }
    
    // drag拖拽触发的事件,连续触发,只要鼠标不松开会一直触发
    box.ondrag = function () {
        this.style.background = 'yellow';
    }
    
    // dragend 拖拽结束时,触发的事件,只要鼠标一松开就触发
    box.ondragend = function () {
        this.style.background = 'skyblue';
    }
    
    Element UI 拖拽排序

    https://element.eleme.cn/#/zh-CN ---》组件(菜单)---》Tree树形控件---》可拖拽节点(右侧)

    1.2. 目标元素(拖拽元素被拖到的对象)事件 ----[H5拖拽的容器事件]
    1. ondragenter :进入目标元素触发

    2. ondragover :进入目标、离开目标之间,连续触发

    3. ondragleave :离开目标元素触发

    4. ondrop :在目标元素上释放鼠标触发

    // dragenter 拖拽元素移入目标元素时触发,鼠标进入才算哦
    wrap.ondragenter = function () {
        this.innerHTML = '释放鼠标';
    }
    
    // dragove  拖拽的元素在目标元素中触发,会连续触发
    wrap.ondragover = function (e) {
        this.style.background = '#999';
        console.log(num++);
        // e.preventDefault();
        return false;
    }
    
    // dragleave  拖拽的元素离开目标元素时触发,鼠标离开才算
    wrap.ondragleave = function () {
        this.innerHTML = '请将元素拖进来';
    }
    
    // drop  在目标元素中松口鼠标触发,如果要触发这个事件,必须先将drapover事件取消默认事件
    wrap.ondrop = function () {
        this.style.background = 'skyblue';
        console.log('你在目标元素中松口了鼠标');
        document.body.removeChild(box);
    }
    
    <style>
        #box {
          position: fixed;
          top: 0;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
    
        #wrap {
          position: fixed;
          top: 0;
          right: 0;
          width: 500px;
          height: 300px;
          background-color: rgba(100, 100, 100, .2);
        }
      </style>
    </head>
    
    <body>
      <div draggable="true" id="box"></div>
      <div id="wrap"></div>
      <script>
        box.ondragstart = function () {
          console.log('开始拖拽……');
          this.style.background = 'blue';
        }
        box.ondrag = function () {
          console.log('正在拖拽……')
          this.style.background = 'yellow'
        }
        box.ondragend = function (e) {
          console.log('拖拽完毕……');
          this.style.background = 'skyblue';
        }
        //目标元素(容器)的四个事件
        wrap.ondragenter = function () {//元素拖入
          this.innerHTML = '请释放鼠标';
        }
        wrap.ondragleave = function () {//元素离开
          this.innerHTML = '请将元素拖进来';
        }
        let num = 0;
        wrap.ondragover = function (e) {//在里面移动
          this.style.background = 'skyblue';
          console.log('num', num++)  //在里面时num一直在++
          e.preventDefault()//清除默认事件,拖拽时要阻止默认事件,才会触发鼠标松开ondrop
          // return false;//阻止默认事件
        }
        wrap.ondrop = function () {//鼠标松开
          this.style.background = 'pink';
          console.log('你在目标元素中松开了鼠标');
          document.body.removeChild(box);//拖拽完毕后在body里删除原来的box元素
        }
      </script>
    </body>
    

    2. 拖拽兼容问题

    只作为了解, 因为现在火狐已经没有兼容问题

    火狐浏览器下需设置dataTransfer对象才可以拖拽除图片外的其他标签

    火狐在没有添加dataTransfer前不能使用ondrag和ondragend事件,其他都可以

      <style>
        #box {
          position: fixed;
          top: 0;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
    
        #wrap {
          position: fixed;
          top: 0;
          right: 0;
          width: 500px;
          height: 300px;
          background-color: rgba(100, 100, 100, .2);
        }
      </style>
    </head>
    
    <body>
      <div draggable="true" id="box"></div>
      <div id="wrap"></div>
      <script>
        box.ondragstart = function (e) {
          console.log('开始拖拽……');
          //火狐老版本兼容问题需要线获取dataTransfer对象
          let data = e.dataTransfer;
          console.log(data)
          this.style.background = 'blue';
        }
        box.ondrag = function () {
          console.log('正在拖拽……')
          this.style.background = 'yellow'
        }
        box.ondragend = function (e) {
          console.log('拖拽完毕……');
          this.style.background = 'skyblue';
        }
        //目标元素(容器)的四个事件
        wrap.ondragenter = function () {//元素拖入
          this.innerHTML = '请释放鼠标';
        }
        wrap.ondragleave = function () {//元素离开
          this.innerHTML = '请将元素拖进来';
        }
        let num = 0;
        wrap.ondragover = function (e) {//在里面移动
          this.style.background = 'skyblue';
          console.log('num', num++)  //在里面时num一直在++
          e.preventDefault()//清除默认事件,拖拽时要阻止默认事件,才会触发鼠标松开ondrop
          // return false;//阻止默认事件
        }
        wrap.ondrop = function () {//鼠标松开
          this.style.background = 'pink';
          console.log('你在目标元素中松开了鼠标');
          document.body.removeChild(box);//拖拽完毕后在body里删除原来的box元素
        }
      </script>
    </body>
    
    2.1. dataTransfer对象

    dataTransfer 是 拖拽事件对象的属性

    1. setData() : 设置数据 key和value(必须是字符串)

    2. getData() : 获取数据,根据key值,获取对应的value

      <style>
        #box {
          position: fixed;
          top: 0;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
    
        #wrap {
          position: fixed;
          top: 0;
          right: 0;
          width: 500px;
          height: 300px;
          background-color: rgba(100, 100, 100, .2);
        }
      </style>
    </head>
    
    <body>
      <div draggable="true" id="box"></div>
      <div id="wrap"></div>
      <script>
        box.ondragstart = function (e) {
          console.log('开始拖拽……');
          let data = e.dataTransfer;
          let color = '#' + Math.random().toString(16).substr(2, 6);
          data.setData('color', color)// 通过dataTransfer对象保存数据     setData() : 设置数据 key和value(必须是字符串)
          console.log(data)
         
          data.effectAllowed = 'copyMove'; //拖动时改变光标样式
          this.style.background = 'blue';
        }
        box.ondrag = function () {
          console.log('正在拖拽……')
          this.style.background = 'yellow'
        }
        box.ondragend = function (e) {
          console.log('拖拽完毕……');
          this.style.background = 'skyblue';
        }
        //目标元素(容器)的四个事件
        wrap.ondragenter = function () {
          this.innerHTML = '请释放鼠标';
        }
        wrap.ondragleave = function () {
          this.innerHTML = '请将元素拖进来';
        }
        let num = 0;
        wrap.ondragover = function (e) {
          this.style.background = 'skyblue';
          console.log('num', num++)
          e.preventDefault()
        }
        wrap.ondrop = function (e) {
          let color = e.dataTransfer.getData('color')//getData() : 获取数据,根据key值,获取对应的value
          this.style.background = color;
          console.log('你在目标元素中松开了鼠标');
          document.body.removeChild(box);
        }
      
      </script>
    </body>
    
    box.ondragstart = function (e) {
        this.style.background = 'blue';
        e.dataTransfer.setData('key', this.id);
        // 火狐必须加上这一行代码才能触发drag和dragend事件
    }
    
    // 设置的key在这里可以使用
    wrap.ondrop = function (e) {
        this.style.background = 'skyblue';
      document.body.removeChild(document.getElementById(e.dataTransfer.getData('key')))//确定删除被拖进来的是哪个元素:先通过e.dataTransfer.getData('key')获取字符串--》再获取被拖的是哪个元素--》删除被拖的元素
    }
    
    1. effectAllowed : 设置光标样式(none, copy, copyLink, copyMove, link, linkMove, move, all 和 uninitialized)

    ,参考上面的例子

     box.ondragstart = function (e) {
        console.log(e.dataTransfer);
        e.dataTransfer.effectAllowed = 'link';
    }
    
    1. 设置拖拽元素影子的样式 setDragImage :三个参数(指定哪个元素作为影子可以是图片,坐标X,坐标Y)
       box.ondragstart = function (e) {
           console.log(e.dataTransfer);
           e.dataTransfer.setDragImage(img, 100, 100);
       }   
    
      <style>
        * {
          margin: 0;
          padding: 0;
        }
    
        #box {
          position: fixed;
          top: 100px;
          left: 0;
          width: 100px;
          height: 100px;
          background-color: red;
        }
    
        #wrap {
          position: fixed;
          top: 0;
          right: 0;
          width: 500px;
          height: 300px;
          background-color: rgba(100, 100, 100, .2);
        }
      </style>
    </head>
    
    <body>
      <img src="./images/333.jpg" id='img' width=100 height=100 alt="">
      <div draggable="true" id="box"></div>
      <div id="wrap"></div>
      <script>
        box.ondragstart = function (e) {
          console.log('开始拖拽……');
          let data = e.dataTransfer;
          let color = '#' + Math.random().toString(16).substr(2, 6);
          data.setData('color', color)
          console.log(data)
    
          //设置拖拽阴影的背景
          data.setDragImage(img, 0, 0)
    
          this.style.background = 'blue';
        }
        box.ondrag = function () {
          console.log('正在拖拽……')
          this.style.background = 'yellow'
        }
        box.ondragend = function (e) {
          console.log('拖拽完毕……');
          this.style.background = 'skyblue';
        }
        //目标元素(容器)的四个事件
        wrap.ondragenter = function () {
          this.innerHTML = '请释放鼠标';
        }
        wrap.ondragleave = function () {
          this.innerHTML = '请将元素拖进来';
        }
        let num = 0;
        wrap.ondragover = function (e) {
          this.style.background = 'skyblue';
          console.log('num', num++)
          e.preventDefault()
        }
        wrap.ondrop = function (e) {
          let color = e.dataTransfer.getData('color')
          this.style.background = color;
          console.log('你在目标元素中松开了鼠标');
          document.body.removeChild(box);
        }
      </script>
    </body>
    
    1. files: 获 取外部拖拽的文件,返回一个filesList列表
      filesList下有个type属性,返回文件的类型
    wrap.ondrop = function (e) {
        const dt = e.dataTransfer;
        console.log(dt.files)
        return false;
    }
    
     <style>
        * {
          margin: 0;
          padding: 0;
        }
        #box {
      position: fixed;
      top: 100px;
      left: 0;
      width: 100px;
      height: 100px;
      background-color: red;
    }
    
    #wrap {
      position: fixed;
      top: 0;
      right: 0;
      width: 500px;
      height: 300px;
      background-color: rgba(100, 100, 100, .2);
    }
    </style>
    </head>
    
    <body> 
      <img src="./images/333.jpg" id='img' width=100 height=100 alt="">
    
      <div draggable="true" id="box"></div>
      <div id="wrap"></div>
      <script>
        box.ondragstart = function (e) {
          console.log('开始拖拽……');
          let data = e.dataTransfer;
          let color = '#' + Math.random().toString(16).substr(2, 6);
          data.setData('color', color)
          console.log(data)
          data.setDragImage(img, 0, 0)
    
    
          this.style.background = 'blue';
        }
        box.ondrag = function () {
          console.log('正在拖拽……')
          this.style.background = 'yellow'
        }
        box.ondragend = function (e) {
          console.log('拖拽完毕……');
          this.style.background = 'skyblue';
        }
        //目标元素(容器)的四个事件
        wrap.ondragenter = function () {
          this.innerHTML = '请释放鼠标';
        }
        wrap.ondragleave = function () {
          this.innerHTML = '请将元素拖进来';
        }
        let num = 0;
        wrap.ondragover = function (e) {
          this.style.background = 'skyblue';
          console.log('num', num++)
          e.preventDefault()
        }
        wrap.ondrop = function (e) {
          console.log(e.dataTransfer.files)//元素拖进来了,可以打印文件的名字,拖进来的文件可以是任何外部的文件
          let color = e.dataTransfer.getData('color')
          this.style.background = color;
          console.log('你在目标元素中松开了鼠标');
          document.body.removeChild(box);
        }
    
      </script>
    </body>
    

    3. 读取读取文件信息

    通过FileReader对象可以读取本地存储的文件信息, 使用File对象 指定要读取的文件数据

    3.1.FileReader(读取文件信息)

    HTML5 新增的内置构造函数,可以读取本地文件的信息

    方法:

    1. readAsDataURL
      参数为要读取的文件对象
    2. onload当读取文件成功完成的时候触发此事件
    3. this. result 获取读取的文件数据
    wrap.ondrop = function (e) {
        const dt = e.dataTransfer;
        const oFile = dt.files.item(0);
    
        // 创建读取文件对象
        const file = new FileReader();
    
        // 获取文件的url
        file.readAsDataURL(oFile)
        
        // 当信息读取完成后执行
        file.onload = function () {
            // console.log(oFile);
            if (oFile.type.includes('image')) {
                const img = new Image();
                img.src = file.result;
                wrap.appendChild(img)
            }
    
        }
        return false;
    }
    

    性能低,没有必要吧这些字符串渲染到页面中

    读取拖入的图片信息,并显示在页面上

     <style>
        #wrap {
          width: 400px;
          height: 100px;
          background-color: #ccc;
          color: #fff;
          text-align: center;
          line-height: 100px;
          font-size: 30px;
          margin: 10px auto;
    
        }
    
        #wraps img {
          width: 100px;
          height: 100px;
        }
      </style>
    </head>
    
    <body>
      <div id="wrap">请将文件拖入到此处</div>
      <div id="wraps"></div>
      <script>
        wrap.ondrop = function (ev) {
          //1.获取拖入文件的文件对象
          // let datafile =ev.dataTransfer.files[0] //获取拖入的文件方法一
          let dataFile = ev.dataTransfer.files.item(0) //获取拖入文件方法二
          console.log(dataFile)//通过文件对象可以看到文件信息
          //创建读取文件对象
          let files = new FileReader();
          console.log(files);
          //读文本信息
          // files.readAsText(dataFile)
          // files.onload = function(){
          //   console.log(this)
          // }
          //读取文件url信息
          files.readAsDataURL(dataFile)
    
          // 读取成功后触发事件
          files.onload = function () {
            console.log('files', this)   //result可以看到图片的base64信息,base64可以减少请求次数
            let img = new Image();
            img.src = this.result;
            wraps.appendChild(img)//把图片加到页面上去,在页面中显示
          }
        }
        /*阻止图片拖入浏览器后默认打开*/
        document.addEventListener('drop', function (e) {
          e.preventDefault()
        }, false)
        document.addEventListener('dragover', function (e) {
          e.preventDefault()
        }, false)
      </script>
    </body>
    
      <style>
        #wrap {
          width: 400px;
          height: 100px;
          background-color: #ccc;
          color: #fff;
          text-align: center;
          line-height: 100px;
          font-size: 30px;
          margin: 10px auto;
    
        }
    
        #wraps img,
        #wraps div {
          width: 100px;
          height: 100px;
        }
    
        #wraps div {
          display: inline-block;
          background-color: pink;
          vertical-align: top;
          /* 默认基线对齐,改为顶部对齐 */
        }
      </style>
    </head>
    
    <body>
      <div id="wrap">请将文件拖入到此处</div>
      <div id="wraps"></div>
      <script>
        wrap.ondrop = function (ev) {
          //多文件的读取
          let dataFiles = [...ev.dataTransfer.files] //多个文件      
          console.log(dataFiles)//通过文件对象可以看到文件信息
    
          dataFiles.forEach(file => {
            console.log('file', file);
            let files = new FileReader();
            console.log(files)
            //判断是否为图片
            if (file.type.includes('image')) {
    
              //读取文件url信息
              files.readAsDataURL(file)
              // 读取成功后触发事件
              files.onload = function () {
                console.log('files', this)   //result可以看到图片的base64信息,base64可以减少请求次数
                let img = new Image();
                img.src = this.result;
                wraps.appendChild(img)//把图片加到页面上去,在页面中显示
              }
            }
    
            else {
              //读文本信息
              files.readAsText(file)
              files.onload = function () {
                let div = document.createElement('div')
                div.innerHTML = this.result;
                wraps.appendChild(div)
              }
            }
          })
        }
        /*阻止图片拖入浏览器后默认打开*/
        document.addEventListener('drop', function (e) {
          e.preventDefault()
        }, false)
        document.addEventListener('dragover', function (e) {
          e.preventDefault()
        }, false)
      </script>
    </body>
    

    多文件的拖入上传

      <style>
        #wrap {
          width: 400px;
          height: 100px;
          background-color: #ccc;
          color: #fff;
          text-align: center;
          line-height: 100px;
          font-size: 30px;
          margin: 10px auto;
    
        }
    
        #wraps img,
        #wraps div {
          width: 100px;
          height: 100px;
        }
    
        #wraps div {
          display: inline-block;
          background-color: pink;
          vertical-align: top;
          /* 默认基线对齐,改为顶部对齐 */
        }
      </style>
    </head>
    
    <body>
      <div id="wrap">请将文件拖入到此处</div>
      <div id="wraps"></div>
      <script>
        wrap.ondrop = function (ev) {
          //多文件的读取
          let dataFiles = [...ev.dataTransfer.files] //多个文件      
          console.log(dataFiles)//通过文件对象可以看到文件信息
    
          dataFiles.forEach(file => {
            console.log('file', file);
            let files = new FileReader();
            console.log(files)
            //判断是否为图片
            if (file.type.includes('image')) {
    
              //读取文件url信息
              files.readAsDataURL(file)
              // 读取成功后触发事件
              files.onload = function () {
                console.log('files', this)   //result可以看到图片的base64信息,base64可以减少请求次数
                let img = new Image();
                img.src = this.result;
                wraps.appendChild(img)//把图片加到页面上去,在页面中显示
              }
            }
    
            else {
              //读文本信息
              files.readAsText(file)
              files.onload = function () {
                let div = document.createElement('div')
                div.innerHTML = this.result;
                wraps.appendChild(div)
              }
            }
          })
        }
        /*阻止图片拖入浏览器后默认打开*/
        document.addEventListener('drop', function (e) {
          e.preventDefault()
        }, false)
        document.addEventListener('dragover', function (e) {
          e.preventDefault()
        }, false)
      </script>
    </body>
    
    
    3.2 利用表单域来读取文件
    1. Files对象

      表单域返回的DOM元素身上有一个files的属性,这个属性值就是一个Files对象, 里面保存选中的文件的信息

    <input type="file" name="file" multiple />
    
    <script>
        var file = document.querySelector("input")
    
        file.addEventListener("change",function(){
            console.log(this.files)
        },false)
    
    </script>
    
    1. FileReader对象

    利用FileReader读取信息

    file.addEventListener("change",function(){
        console.log(this.files)
        var oFile = this.files[0]
        var readfile = new FileReader()
    
        readfile.readAsDataURL(oFile)
        readfile.onload = function(){
            var img = new Image()
            img.src= this.result;
            box.appendChild(img)
        }
    },false)
    
      <style>
        #wrap {
          width: 400px;
          height: 100px;
          background-color: #ccc;
          color: #fff;
          text-align: center;
          line-height: 100px;
          font-size: 30px;
          margin: 10px auto;
        }
        #wraps img,
        #wraps div {
          width: 100px;
          height: 100px;
        }
        #wraps div {
          display: inline-block;
          background-color: pink;
          vertical-align: top;
          /* 默认基线对齐,改为顶部对齐 */
        }
      </style>
    </head>
    
    <body>
      <!-- 不用鼠标拖拽,用input选择文件 -->
      <input type="file" name="" id="file" multiple> <!-- multiple代表可以一次选多张图片 -->
      <div id="wraps"></div>
       <script>
        file.onchange = function () { //文件一旦改变会触发事件,会读取到文件
          console.log(this.files)
          //多文件的读取
          let dataFiles = [...this.files] //多个文件      
          console.log(dataFiles)//通过文件对象可以看到文件信息
    
          dataFiles.forEach(file => {
            console.log('file', file);
            let files = new FileReader();
            console.log(files)
            //判断是否为图片
            if (file.type.includes('image')) {
    
              //读取文件url信息
              files.readAsDataURL(file)
              // 读取成功后触发事件
              files.onload = function () {
                console.log('files', this)   //result可以看到图片的base64信息,base64可以减少请求次数
                let img = new Image();
                img.src = this.result;
                wraps.appendChild(img)//把图片加到页面上去,在页面中显示
              }
            }
    
            else {
              //读文本信息
              files.readAsText(file)
              files.onload = function () {
                let div = document.createElement('div')
                div.innerHTML = this.result;
                wraps.appendChild(div)
              }
            }
          })
        }
      </script>
    </body>
    

    相关文章

      网友评论

        本文标题:HTML5拖拽事件

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