HTML5之拖拽和拖放

2,248 阅读3分钟

拖拽/拖放

拖放(drap&drop)在我们平时的工作中,经常遇到。它表示:抓取对象以后拖放到另一个位置。目前,它是HTML5标准的一部分。

拖放的基本操作

选中=>拖动=>释放
选中

在H5标准中,为了使元素克拖动,把draggable属性设置为true。文本、图片和链接式默认可以拖放的,它们的draggable属性默认被设置了true。

图片和链接按住鼠标左键选中,就可以拖放。

文本只有在被选中的情况下才能拖放。如果显示设置为恩本的draggable属性为true,按住鼠标左边也可以直接拖放。

语法

<element draggle="true|false|auto"></element>
  • true: 可以拖动
  • false: 禁止拖动
  • auto: 跟随浏览器定义是否可以拖动
拖动

每个可拖动的元素,在拖动过程中,都会经历三个过程:

拖动开始=>拖动过程中=>拖动结束
对象事件名称描述
被拖动的元素对象dragstart在元素开始被拖动时候触发
drag在元素被拖动时反复触发
dragend在拖动操作完成时触发
对象事件名称描述
目标对象dragenter当被拖动元素进入目标元素占据的屏幕空间时触发
dragover当被拖动元素在目标元素内时触发
dragleave当被拖动元素没有放下就离开目标元素时触发

注意:dragenter和dragover事件的默认行为是拒绝接受任何被拖放的元素。因此,我们必须阻止浏览器这种默认行为。e.prevenDefault();

释放

到达目的地之后,释放元素事件

对象事件名称描述
目标对象drop当被拖动元素在目标元素里放下时触发,一般需要取消浏览器的默认行为。

看个例子演示每个API

<!DOCTYPE HTML>
<html>
    <head>
        <title>拖放示例-文本</title>
    </head>
    <style>
        #current{
            border: 1px solid #000;
            padding: 20px;
            margin-bottom: 20px;
        }
        #target{
            border: 1px solid #f00;
            width: 400px;
            height: 400px;
        }
        .box{
            width: 100px;
            height: 100px;
            border: 1px solid #FF6700;
        }
    </style>
    <body>
        <p>不能被拖拽的文字</p>
        <div id="current">
            <div class="text" id="text">
                <p draggable="true">可拖拽的文字</p>
                <img src="img_submit.gif" alt="">
                <div class="box" draggable="true"></div>
            </div>
        </div>
        <div id="target"></div>
        <script>
            var text = document.getElementById('text');
            var target = document.getElementById('target');
            text.ondragstart = function(event){
                console.log('元素开始被拖动');
            }
            text.ondrag = function(e){
                // console.log('一直被拖拽着');
            }
            text.ondragend = function(e){
                console.log('拖拽操作完成时触发');
            }
            target.ondragenter = function(e){
                console.log('进入了所要的目标对象中');
                e.preventDefault()
            }
            target.ondragover = function(e){
                console.log('在目标元素内触发');
                e.preventDefault();
            }
            target.ondragleave = function(e){
                console.log('拖拽着元素没有放下,并离开目标对象时');
                // e.preventDefault();
            }
            target.ondrop = function(event){
                console.log('被拖拽元素在目标元素里放下是触发');
                event.preventDefault();
            }
        </script>
    </body>
</html>

效果展示:

由上个例子我们可以看出我们确实实现了拖放的功能,猜想:能否让我们拖拽的元素放到指定的目标对象上呢?答案是可以的,如果想实现该功能,就要学一下DataTransfer对象了

DataTransfer对象

在进行拖放操作时,DataTransfer对象用来保存,通过拖放操作,拖动到浏览器的数据。它可以保存一项或多项数据、一种或者多种数据类型。

event.DataTransfer
方法

【1】DataTransfer.setData()

该方法用来设置拖动操作的当前数据

语法:

DataTransfer.setData(format,data);
  • format 拖动数据的MIME类型,通常text/plaintext/uri-list
  • data 要添加的数据

【2】DataTransfer.getData()

接收指定类型的拖放数据。如果拖放行为没有操作任何数据,则返回一个空字符串。返回值是字符串类型

语法:

dataTransfer.getData(format);
  • format 拖动数据的MIME类型,通常text/plaintext/uri-list

【3】DataTransfer.clearData()

删除给定类型拖动操作的数据。

【4】DataTransfer.setDragImage()

可以使用该方法来拖拽图片

语法:

DataTransfer.setDragImage(img,xOffset,yOffset)
  • img:拖拽图像的当前元素
  • xOffset :图片的横向偏移量
  • yOffset: 图片的纵向偏移量

定义拖动效果

dropEffect属性可以定义完成具体的效果

我们可以定义三种效果:

  1. copy 表示拖动的数据将从其当前位置复制到放置位置。
  2. move 表示拖动的数据将从其当前位置移动到放置位置。
  3. link 表示将在源位置和放置位置之间创建某种形式的关系或连接。

例子:实现复制和移动元素

<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title></title>
        <style>
            #copy,#move{
                border: 1px solid #000;
                width: 300px;
                height: 200px;
            }
            #copyTarget,#moveTarget{
                width: 300px;
                height: 200px;
                border: 1px solid #FF0000;
            }
            #newId{
                width: 200px;
                height: 50px;
                border: 1px solid darkcyan;
            }
        </style>
    </head>
    <body>
        <h2>使用拖拽实现移动和复制功能</h2>
        <div draggable="true" id="copy">要复制的元素</div>
        <div id="copyTarget"></div>
        <div draggable="true" id="move">要移动的元素</div>
        <div id="moveTarget"></div>
        <script type="text/javascript">
            window.onload = function() {
                // 复制
                $('copy').ondragstart = handler_dragstart;
                $('copy').ondragend = handler_dragend;
                $('copyTarget').ondragover = hander_dragover;
                $('copyTarget').ondragleave = handler_dragLeave
                $('copyTarget').ondrop = handler_drop;
                // 移动
                $('move').ondragstart = handler_dragstart;
                $('move').ondragend = handler_dragend;
                $('moveTarget').ondragover = hander_dragover;
                $('moveTarget').ondragleave = handler_dragLeave
                $('moveTarget').ondrop = handler_drop;
                function handler_dragstart(event) {
                    console.log('拖拽开始');
                    // 设置数据
                    event.dataTransfer.setData('text/plain', event.target.id);
                    // 设置拖动效果 设置既复制又移动
                    event.effectAllowed = 'copyMove';
                }
                function handler_dragend(event) {
                    // 拖动操作完成时 清空设置的数据
                    // event.target.style.borderColor = 'black';
                    event.dataTransfer.clearData();
                }
                // 当被拖动元素在目标元素内时触发
                function hander_dragover(event) {
                    event.target.style.background = 'lightblue';
                    event.preventDefault();
                }
                function handler_drop(event) {
                    event.preventDefault();
                    // 获取设置的数据
                    var id = event.dataTransfer.getData('text/plain');
                    if (id === 'copy' && event.target.id == 'copyTarget') {
                        var nodeCopy = document.getElementById(id).cloneNode(true);
                        nodeCopy.id = 'newId';
                        event.target.appendChild(nodeCopy);
                    }
                    if(id === 'move' && event.target.id == 'moveTarget'){
                        event.target.appendChild(document.getElementById(id));
                        console.log(event.target.children);
                    }
                }
                function handler_dragLeave(event) {
                    event.target.style.background = 'white';
                    event.preventDefault();
                }
                function $(ele) {
                    return document.getElementById(ele);
                }
            }
        </script>
    </body>
</html>

效果展示:

例子:实现简单拖拽购物车功能

<html>
    <head>
        <meta charset="utf-8" />
        <title>使用拖放API将商品拖入购物车</title>
        <style>
            body {
                font-size: 12px
            }
            .liT {
                border-bottom: solid 1px #ccc;
                background-color: #eee;
                font-weight: bold
            }
            .liF {
                float: left;
                margin-right: 5px;
            }
            ul {
                list-style-type: none;
                padding: 0px;
                height: 106px;
                width: 330px
            }
            ul li {
                overflow: hidden;
            }
            ul li img {
                width: 68px;
                height: 96px;
                border: solid 1px #ccc;
                padding: 3px
            }
            ul li span {
                float: left;
                width: 70px;
                padding: 5px;
            }
        </style>
    </head>
    <body>
        <ul>
            <li class="liF">
                <img src="image01.png" id="img02" alt="42" title="2006作品" draggable="true">
            </li>
            <li class="liF">
                <img src="image02.png" id="img03" alt="56" title="2008作品" draggable="true">
            </li>
            <li class="liF">
                <img src="image03.png" id="img04" alt="52" title="2010作品" draggable="true">
            </li>
        </ul>
        <ul id="ulCart">
            <li class="liT">
                <span>书名</span>
                <span>定价</span>
                <span>数量</span>
                <span>总价</span>
            </li>
        </ul>
        <script type="text/javascript">
            pageload();
            function $$(id) {
               return document.getElementById(id);
            }
            //自定义页面加载时调用的函数
            function pageload() {
                //获取全部的图书商品
                var Drag = document.getElementsByTagName("img");
                //遍历每一个图书商品
                for (var intI = 0; intI < Drag.length; intI++) {
                    console.log(Drag[intI]);
                    //为每一个商品添加被拖放元素的dragstart事件
                    Drag[intI].addEventListener("dragstart", function(e) {
                        e.dataTransfer.clearData();
                        var objDtf = e.dataTransfer;
                        console.log(objDtf);
                        objDtf.setData("text/plain", addCart(this.title, this.alt, 1));
                    },true);
                }
                var Cart = $$("ulCart");
                //添加目标元素的drop事件
               Cart.addEventListener("drop",function(e) {
                    var objDtf = e.dataTransfer;
                    var strHTML = objDtf.getData("text/plain");
                    var num = top_();
                    Cart.innerHTML += strHTML;
                    var lists = document.getElementsByClassName('liC');
                    for(var i = 0; i < lists.length; i++){
                        var spans = lists[i].children;
                        console.log(spans);
                        spans[2].innerHTML = num;
                        spans[3].innerHTML = num * spans[1].innerHTML;
                    }
                    e.preventDefault();
                    e.stopPropagation();
                },false);
            }
            //添加页面的dragover事件
            document.ondragover = function(e) {
                //阻止默认方法,取消拒绝被拖放
                e.preventDefault();
            }
            //添加页面drop事件
            document.ondrop = function(e) {
                //阻止默认方法,取消拒绝被拖放
                e.preventDefault();
            }
            //自定义向购物车中添加记录的函数
            function addCart(a, b, c) {
                var strHTML = `<li class = 'liC'>
                            <span>${a}</span>
                            <span class="price">${b}</span>
                            <span class="num">${c}</span>
                            <span class="sum">${b*c}</span>
            			</li>`
                return strHTML;
            }
            //提示输入框
            function top_() {
                var str = prompt("请输入要购买的数量", 1);
                return str;
            }
        </script>
    </body>
</html>