常见的拖拽效果,以及最新的h5拖拽效果及其原理解析

本文详细介绍了如何使用HTML5的draggable属性以及相关事件(如ondragstart,ondragover,ondragenter,ondragend)实现列表元素的拖拽排序效果。开发者需理解并应用这些事件来控制元素的拖放行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先是使用h5的api实现拖拽排序效果
需要实现的效果
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      display: flex;
      flex-direction: row;
      align-content: center;
      justify-content: center;
      align-items: center;
    }
    .list {
      /* 去除ul小点 */
      list-style: none;
    }
    .list-item {
      user-select: none;
      width: 400px;
      height: 35px;
      line-height: 35px;
      text-align: center;
      border: 1px solid #ccc;
      /* 渐变背景 */
      background: linear-gradient(to right, #015d69, #51b9ff);
      cursor: move;
      color: #fff;
      border-radius: 10px;
    }

    .list-item.moving {
      background: transparent;
      color: transparent;
      border: 1px dashed #ccc;
    }
  </style>
</head>

<body>
  <ul class="list">
    <li draggable="true" class="list-item">1</li>
    <li draggable="true" class="list-item">2</li>
    <li draggable="true" class="list-item">3</li>
    <li draggable="true" class="list-item">4</li>
    <li draggable="true" class="list-item">5</li>
    <li draggable="true" class="list-item">6</li>
    <li draggable="true" class="list-item">7</li>
    <li draggable="true" class="list-item">8</li>
  </ul>
  <script>
    const list = document.querySelector('.list');
    let sourceNode; //当前在拖动的节点
    list.ondragstart = e => {
      setTimeout(() => {
        e.target.classList.add('moving')
      }, 0);
      sourceNode = e.target
      e.dataTransfer.effectAllowed = 'move';
    }
    list.ondragover = e => {
      e.preventDefault()
    }
    list.ondragenter = e => {
      e.preventDefault();
      if (e.target === list || e.target === sourceNode) {
        return
      }
      const children = Array.from(list.children)
      const sourceIndex = children.indexOf(sourceNode)
      const targetIndex = children.indexOf(e.target)
      if (sourceIndex < targetIndex) {
        list.insertBefore(sourceNode, e.target.nextElementSibling)
      } else {
        list.insertBefore(sourceNode, e.target)
      }
    }
    list.ondragend = e => {
      e.target.classList.remove('moving')
    }
  </script>
</body>
</html>

原理解析
这是因为使用了h5的 draggable属性,页面中设置了 draggable=“true” 属性的元素可以进行拖拽
示例如下
代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      display: flex;
      flex-direction: row;
      align-content: center;
      justify-content: space-evenly;
      align-items: center;
    }

    .box {
      width: 200px;
      height: 200px;
      background-color: red;
      line-height: 200px;
      text-align: center;
    }
  </style>
</head>

<body>
  <div class="box">未添加draggable</div>
  <div draggable="true" class="box">添加了draggable</div>
</body>

</html>

效果示例
在这里插入图片描述
给 box1 增加了draggable=“true” 属性之后, box1 就变成可以拖拽的了。但是拖拽之后要做什么事情?就涉及到事件监听。

拖拽元素的事件监听:(应用于拖拽元素)

  • ondragstart当拖拽开始时调用
  • ondragleave 当鼠标离开拖拽元素时调用
  • ondragend 当拖拽结束时调用
  • ondrag 整个拖拽过程都会调用

演示一下

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      display: flex;
      flex-direction: row;
      align-content: center;
      justify-content: space-evenly;
      align-items: center;
    }

    .box {
      width: 200px;
      height: 200px;
      background-color: red;
      line-height: 200px;
      text-align: center;
    }
  </style>
</head>

<body>
  <div class="box">未添加draggable</div>
  <div id="box" draggable="true" class="box">添加了draggable</div>
  <script>
    var box = document.querySelector('#box');
    //  绑定拖拽事件

    //  拖拽开始
    box.ondragstart = function () {
      console.log('拖拽开始.');
    }

    //  拖拽离开:鼠标拖拽时离开被拖拽的元素时触发
    box.ondragleave = function () {
      console.log('拖拽离开..');
    }

    //  拖拽结束
    box.ondragend = function () {
      console.log('拖拽结束...');
      console.log("---------------");
    }

    box.ondrag = function () {
      console.log('拖拽');
    }

  </script>
</body>

</html>

效果展示

请忽略那些报错,那是浏览器插件的报错
请添加图片描述

目标元素

拖动元素侦听完成了,剩下的就是实现如何的把元素放到目标元素那里去了

比如说,你想把元素A拖拽到元素B里,那么元素B就是目标元素。

页面中任何一个元素都可以成为目标元素。

目标元素的事件监听:(应用于目标元素)

  • ondragenter 当拖拽元素进入时调用
  • ondragover 当拖拽元素停留在目标元素上时,就会连续一直触发(不管拖拽元素此时是移动还是不动的状态)
  • ondrop 当在目标元素上松开鼠标时调用
  • ondragleave 当鼠标离开目标元素时调用
    效果如下

请添加图片描述

代码示例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      display: flex;
      flex-direction: row;
      align-content: center;
      justify-content: space-evenly;
      align-items: center;
    }

    .box {
      width: 200px;
      height: 200px;
      background-color: red;
      line-height: 200px;
      text-align: center;
    }

    .target-box {
      width: 500px;
      height: 500px;
      background-color: green;
      line-height: 300px;
      text-align: center;
    }
  </style>
</head>

<body>
  <div class="box">未添加draggable</div>
  <div id="box" draggable="true" class="box">添加了draggable</div>
  <div class="target-box"></div>
  <script>
    // var box = document.querySelector('#box');
    // //  绑定拖拽事件

    // //  拖拽开始ondragstart 触发
    // box.ondragstart = function () {
    //   console.log('拖拽开始.');
    // }

    // //  拖拽离开:鼠标拖拽时离开被拖拽的元素时ondragleave 触发
    // box.ondragleave = function () {
    //   console.log('拖拽离开..');
    // }

    // //  拖拽结束ondragend 事件触发
    // box.ondragend = function () {
    //   console.log('拖拽结束...');
    //   console.log("---------------");
    // }

    // box.ondrag = function () {
    //   console.log('拖拽');
    // }
    var two = document.querySelector('.target-box');

    //目标元素的拖拽事件

    // 当被拖拽元素进入时ondragenter 触发
    two.ondragenter = function () {
      console.log("移入目标盒子.");
    }

    // 当被拖拽元素离开时ondragleave 触发
    two.ondragleave = function () {

      console.log("移出目标盒子");
    }

    // 当拖拽元素在 目标元素上时,ondragover 会连续触发
    two.ondragover = function (e) {
      //阻止拖拽事件的默认行为
      e.preventDefault(); 

      console.log("在目标盒子上");
    }

    // 当在目标元素上松开鼠标时ondrop 触发
    two.ondrop = function () {
      console.log("在目标盒子上松开了鼠标");
    }
  </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Qayrup

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

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

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

打赏作者

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

抵扣说明:

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

余额充值