js拖拽事件详解

拖放事件

拖放是由拖动与释放两部分组成,拖放事件也分为被拖动元素的相关事件,和容器的相关事件。
被拖动元素的相关事件如下所示:

事件描述
dragstart用户开始拖动元素时触发
drag元素正在拖动时触发
dragend用户完成元素拖动后触发

容器相关事件如下所示:

事件描述
dragenter当被鼠标拖动的对象进入目标容器时触发此事件
dragover当被拖动的对象在目标容器范围内拖动时触发此事件
dragleave当被鼠标拖动的对象离开目标容器时触发此事件
drop在一个拖动过程中,释放鼠标键到目标容器时触发此事件

如何实现元素的拖放

首先创建一个HTML文本,用于测试代码,如下所示:

<!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>HTML5学习</title>
            <style type="text/css">
                .div1{
                    width:200px;
                    height:100px;
                    padding:20px;
                    border:1px solid #000;
                }
                p{
                    font-size: 28px;
                }
            </style>
        </head>
        <body>
            <div>
                <div class="div1" id="div1" ></div>
                <p id="drag1">Hello World</p>
            </div>
        </body>
    </html>

然后,我们要给被拖动元素(也就是在上述的 < p > 标签上),设置一个 draggable 属性,此属性用于规定元素是否可拖动,当属性值为 true 时表示元素可拖动,为 false 表示元素不可拖动。

<p id="drag1" draggable="true">Hello World</p>

只有设置了 draggable 属性值为 true ,指定元素才能被拖动。

然后,我们要做的是点击被拖动元素p标签,点击这个元素时需要触发一个 ondragstart 事件,ondragstart 事件会在用户开始拖动元素或选择的文本时触发。调用了一个 drag(event) 函数,在个[函数中规定被拖动的数据,如下所示:

function drag(e){
    e.dataTransfer.setData("Text", e.target.id);
}

代码中的 dataTransfer.setData() 方法用于设置被拖数据的数据类型和值。参数 Text 表示被拖动数据的数据类型,参数 e.target.id 是可拖动元素的 id。

接着,我们将要 “Hello World” 拖动到元素容器范围内(矩形框中)。要实现这个步骤,需要在放置拖动元素的容器上绑定一个 ondragover 事件,这个事件用于规定在何处放置被拖动的数据。

默认情况下,是无法将一格元素放置到另外一个元素里面的,所以如果需要设置允许放置,则要在 ondragover 事件中加上 e.preventDefault() 方法来阻止默认行为。

function allowDrop(e){
    e.preventDefault();
}

最后,就是要放置被拖动元素,也就是要在元素容器范围内松开鼠标。需要在元素容器上绑定一个 ondrop 事件,如下所示,这个事件会在拖动过程中释放鼠标键时触发。

<div id="div1" class="div1" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>

<script>
    function drop(e){
        e.preventDefault();
        var data = e.dataTransfer.getData("Text");
        e.target.appendChild(document.getElementById(data));
    }
</script>

在 ondrop 事件中同样需要调用 e.preventDefault() 方法来阻止默认行为。然后可以通过 dataTransfer.getData(“Text”); 方法获取之前的 drag(event) 函数中保存的信息,也就是被拖动元素的 id。接着通过 target.appendChild() 方法为将拖动元素作为元素容器的子元素追加到元素容器中,这样就能成功实现拖放。

完整代码

完整代码如下所示:

<!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>HTML5学习</title>
            <style type="text/css">
                .div1{
                    width:200px;
                    height:100px;
                    padding:20px;
                    border:1px solid #000;
                }
                p{
                    font-size: 28px;
                }
            </style>
        </head>
        <body>
            <div>
                <div id="div1" class="div1" ondrop="drop(event)" ondragover="allowDrop(event)" ></div>
                <p id="drag1" draggable="true" ondragstart="drag(event)">Hello World</p>
            </div>
            <script>
                function drag(e){
                    e.dataTransfer.setData("Text", e.target.id);
                }
                function allowDrop(e){
                    e.preventDefault();
                }
                function drop(e){
                    e.preventDefault();
                    var data = e.dataTransfer.getData("Text");
                    e.target.appendChild(document.getElementById(data));
                }
            </script>
        </body>
    </html>

附加两份案例代码,图片自备,已经在css设置好图片样式,不需要考虑图片大小,图片引进来即可

第一个

效果图
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>九宫格拖拽</title>
    <style>
      * {
        padding: 0;
        margin: 0;
        list-style: none;
      }
      ul {
        width: 300px;
        height: 300px;
        display: flex;
        flex-wrap: wrap;
      }
      li {
        width: 98px;
        height: 98px;
        border: 1px solid;
      }
      p {
        width: 100%;
        height: 100%;
        line-height: 98px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <ul>
      <li><p draggable="true" style="background-color: aqua">1</p></li>
      <li><p draggable="true" style="background-color: red">2</p></li>
      <li><p draggable="true" style="background-color: blue">3</p></li>
      <li><p draggable="true" style="background-color: pink">4</p></li>
      <li><p draggable="true" style="background-color: yellow">5</p></li>
      <li><p draggable="true" style="background-color: green">6</p></li>
      <li></li>
      <li></li>
      <li></li>
    </ul>

    <script>
      let ps = document.querySelectorAll("p");
      let lis = document.querySelectorAll("li");
      let old;
      // 将p的索引值定位id值
      for (let r = 0; r < ps.length; r++) {
        ps[r].setAttribute("id", r);
      }

      function xj() {
        //拖动的元素操作
        for (let i = 0; i < ps.length; i++) {
          ps[i].addEventListener("dragstart", function (e) {
            e.dataTransfer.setData("xj", e.target.id);
            old = this.parentNode;
          });
        }
      }

      xj();

      //容器操作
      for (let c = 0; c < lis.length; c++) {
        lis[c].addEventListener("dragover", function (e) {
          e.preventDefault();
        });

        lis[c].addEventListener("drop", function (e) {
          e.preventDefault();
          let d = e.dataTransfer.getData("xj");
          let oold = this.children[0];
          const newID = document.getElementById(d);

          if (oold) {
            this.appendChild(newID);
            this.removeChild(oold);
            old.appendChild(oold);
          } else {
            this.appendChild(newID);
          }
        });
      }
    </script>
  </body>
</html>

效果图

在这里插入图片描述

这里没有完全按照这个样式写,只是实现了功能,各位觉得不好看的话,完全可以自己改样式

实现功能:将右侧图片拖到左侧框内,相同图片能追加进去,图片不同则追加不上,这里的追加不是新创建,而是把ul>li的元素移动到新容器,简单来说就是左边添加一个,右边减少一个
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            list-style: none;
            text-decoration: none;
        }

        body {
            display: flex;
        }

        ul {
            display: flex;
            flex-wrap: wrap;
            width: 300px;
            height: 500px;
        }

        li {
            width: 60px;
            height: 60px;
            border: 1px solid;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        img {
            width: 50px;
            height: 50px;
        }

        div {
            margin: 100px auto;
            width: 500px;
            height: 700px;
            border: 1px solid;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-around;
        }

        main {
            width: 100px;
            height: 100px;
            border: 1px solid;
        }

        main>img {
            margin-left: calc(50% - 25px);
        }

        nav {
            width: 100%;
            height: 40px;
            border: 1px solid;
        }
    </style>
</head>

<body>

    <div>
        <main id="0">
            <img src="./imgages怪兽/1.jpg" alt="">
            <nav></nav>
        </main>
        <main id="1">
            <img src="./imgages怪兽/2.jpg" alt="">
            <nav></nav>
        </main>
        <main id="2">
            <img src="./imgages怪兽/3.jpg" alt="">
            <nav></nav>
        </main>
        <main id="3">
            <img src="./imgages怪兽/4.jpg" alt="">
            <nav></nav>
        </main>
        <main id="4">
            <img src="./imgages怪兽/5.jpg" alt="">
            <nav></nav>
        </main>
        <main id="5">
            <img src="./imgages怪兽/6.jpg" alt="">
            <nav></nav>
        </main>
        <main id="6">
            <img src="./imgages怪兽/7.jpg" alt="">
            <nav></nav>
        </main>
        <main id="7">
            <img src="./imgages怪兽/8.jpg" alt="">
            <nav></nav>
        </main>
        <main id="8">
            <img src="./imgages怪兽/9.jpg" alt="">
            <nav></nav>
        </main>
        <main id="9">
            <img src="./imgages怪兽/10.jpg" alt="">
            <nav></nav>
        </main>
    </div>

    <ul>
        <!-- 只有设置了 draggable 属性值为 true ,指定元素才能被拖动。 -->
        <li draggable="true" id="0"><img src="./imgages怪兽/1.jpg" alt=""></li>
        <li draggable="true" id="1"><img src="./imgages怪兽/2.jpg" alt=""></li>
        <li draggable="true" id="2"><img src="./imgages怪兽/3.jpg" alt=""></li>
        <li draggable="true" id="3"><img src="./imgages怪兽/4.jpg" alt=""></li>
        <li draggable="true" id="4"><img src="./imgages怪兽/5.jpg" alt=""></li>
        <li draggable="true" id="5"><img src="./imgages怪兽/6.jpg" alt=""></li>
        <li draggable="true" id="6"><img src="./imgages怪兽/7.jpg" alt=""></li>
        <li draggable="true" id="7"><img src="./imgages怪兽/8.jpg" alt=""></li>
        <li draggable="true" id="8"><img src="./imgages怪兽/9.jpg" alt=""></li>
        <li draggable="true" id="9"><img src="./imgages怪兽/10.jpg" alt=""></li>
    </ul>
    <script>
        let lis = document.querySelectorAll("li")
        let main = document.querySelectorAll("div>main")
        let nav = document.querySelectorAll("div>main>nav")
        for (let i = 0; i < lis.length; i++) {
            //循环给所有li绑定事件

            //用户开始拖动元素时触发的事件
            lis[i].addEventListener("dragstart", function (e) {
                //dataTransfer.setData() 方法用于设置被拖数据的数据类型和值。参数 Text 表示被拖动数据的数据类型,参数 e.target.id 是可拖动元素的 id。(亲测e.target也可以)
                //这个text随便设置,目的是让放置容器获取到我们被拖动的li的元素的信息
                e.dataTransfer.setData = ("Text", e.target.id)
            })

            //当被拖动的对象在另一对象容器(放置容器)范围内拖动时触发此事件
            main[i].addEventListener("dragover", function (e) {
                //默认情况下,是无法将一格元素放置到另外一个元素里面的,所以如果需要设置允许放置,则要在 dragover 事件中加上 e.preventDefault() 方法来阻止默认行为。
                e.preventDefault()
            })

            //在一个拖动过程中,释放鼠标键时触发此事件
            main[i].addEventListener("drop", function (e) {
                // 在 drop 事件中同样需要调用 e.preventDefault() 方法来阻止默认行为。然后可以通过 dataTransfer.getData("Text"); 方法获取之前的 drag(event) 函数中保存的信息,也就是被拖动元素的 id。接着通过 target.appendChild() 方法为将拖动元素作为元素容器的子元素追加到元素容器中,这样就能成功实现拖放。
                e.preventDefault()
                //通过 dataTransfer.getData("Text"); 方法获取之前的 drag(event) 函数中保存的信息
                var data = e.dataTransfer.getData("Text")
                console.log(data);
                console.log(e.target);
                //可以发现打印出来的是图片的地址,因为我这里有中文所以需要通过解码来获得解码后的data信息
                let xj = decodeURI(data)
                console.log(xj);

                //将获得的地址提取里面的序号,从1到10(因为是提取图片地址的序号,图片是从1开始的)
                let arr = xj.replaceAll("/", "=").split("=")[5].split(".")[0]
                console.log(arr);//1/2/3/4/5/6/7/8//9/10
                //打印当前点击的main标签的id值,是字符串需要转换字符类型,又是从0开始,arr是从一开始的,所以这里要加1
                console.log(arr, parseInt(main[i].getAttribute("id")) + 1);
                //判断当前拖拽的图片序号是否与当前的main的id值一致,如果一致的话就进入if判断,否则没效果
                if (arr == parseInt(main[i].getAttribute("id")) + 1) {
                    //将拖拽的元素追加到main的nav下面,这样就实现了对应的图片放到对应的位置
                    nav[i].appendChild(lis[i]);
                    console.log(1);
                }
            })
        }

    </script>
</body>

</html>

总结

当我们要对某个元素实行拖放操作时,首先就需将这个元素的 draggable 属性设置为 true,表示允许元素拖动。其中图片和链接默认是可拖动的,不需设置要 draggable 属性。

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寂173

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值