拖拽事件

一、拖拽事件相关的API介绍

想详细了解的请去MDN网站查看具体相关API

拖拽操作 - Web API | MDN

这边介绍比较重要的几个API:

1.首先是 draggabel (可拖拽),在 HTML 中,除了图像、链接和选择的文本默认的可拖拽行为之外,其他元素在默认情况下是不可拖拽的。要使其他的HTML元素可拖拽,必须做三件事:

2.就是通过dragstart事件添加监听属性或设置事件处理器属性,dataTransfer来持有拖拽数据。dataTransfer持有包含两个信息,数据的类型(或格式)和数据值。

event.dataTransfer.setData("text/plain", "Text to drag");
//参数依次为数据类型和数据
<div  draggable="true" class="child"></div>

<script>

 const child = document.querySelector('.child');
//添加监听事件
child.addEventListener('dragstart', (e) => {
            //设置拖拽数据
            e.dataTransfer.setData('text/plain', 'child');
        }
)

//设置事件处理器属性
//child.ondragstart = e =>{
   //  e.dataTransfer.setData('text/plain', 'child');
//}

</script>

二、拖拽事件实际应用

1、拖拽嵌套案例

<div class="father">  
    <p>
        put here!
    </p> 
</div>
<div draggable="true" class="child"></div>

<script>
     const child = document.querySelector('.child');
     const father = document.querySelector('.father'); 

        child.addEventListener('dragstart', (e) => {
            e.dataTransfer.setData('text/plain', 'child');
        });

        father.addEventListener('dragover', (e) => {
            e.preventDefault();
        });

        father.addEventListener('drop', (e) => {
            const data = e.dataTransfer.getData('text/plain');
            if (data === 'child') {
                father.appendChild(child);
            }
        });
</script>

<style>
     .father {
            width: 200px;
            height: 200px;
            background-color: red;
        }

        .child {
            width: 100px;
            height: 100px;
            background-color: blue;
        }
</style>

2、列表拖拽案例

<body>
     <ul class="list">
            <li class="list-item" draggable="true">1</li>
            <li class="list-item" draggable="true">2</li>
            <li class="list-item" draggable="true">3</li>
            <li class="list-item" draggable="true">4</li>
            <li class="list-item" draggable="true">5</li>
        </ul>

const list = document.querySelector('.list');
let sourceNode;


<script>
//设置保存拖拽的元素
 list.ondragstart = function (e) {
//直接设置元素样式会导致鼠标选中的元素和原来位置的样式一致,设置settimeout之后,选中移动时候会保持原来的样式。
  setTimeout(() => {
            e.target.classList.add('moving');
        },0)
            sourceNode = e.target;
        }
//放入的元素取消默认行为
  list.ondragover = function (e) {
            e.preventDefault();
        }

//拖拽的元素放入到其他列表项的操作
        list.ondragenter = function (e) {
//当元素为整个列表或本身时,不做任何操作
            if (e.target === list || e.target === sourceNode) {
               return;
            }
            const children = Array.from(list.children);
            const targetIndex = children.indexOf(e.target);
            const sourceIndex = children.indexOf(sourceNode);
//根据比较拖拽的元素和进入的元素的index,当目标元素大于拖拽元素时,将拖拽元素放置目标元素后面,小于时,效果相反
            if (targetIndex > sourceIndex) {
                list.insertBefore(sourceNode, e.target.nextSibling);
            } else {
                console.log(e.target);
                list.insertBefore(sourceNode, e.target);
            }

}
//拖拽完成后取消透明样式
   list.ondragend = function (e) {
            e.target.classList.remove('moving'); 
        }

</script>   

<style>
      .list {
            width: 200px;
            height: 200px;
            list-style: none;
            padding: 0;
            margin: 0;
        }

        .list-item {
            width: 100px;
            height: 20px;
            background-color: blue;
            margin: 10px 0;
        }


        .list-item.moving{
            background: transparent;
            color: transparent;
            border: 1px solid black
        }

</style>
</body>    
posted @ 2025-02-16 22:13  imetal  阅读(25)  评论(0)    收藏  举报