JavaScript 练手小技巧:拖拽事件、把图片拖拽入页面

HTML5 新增了拖拽事件 drag,利用它可以实现把外部文件拖拽入页面中,可以实现文件的读取,上传等等功能。

拖拽,又叫拖拉、拖动,英文为 drag

拖拽事件是 HTML5 新增的事件操作。

拖拽指的是,用户在某个对象上按下鼠标键不放,拖动它到另一个位置(另一个标签),然后释放鼠标键,将该对象放在那里。

  • 被拖拽对象:鼠标拖拽的内容,可以是标签,图片,文字等。

  • 容器:被拖拽对象存放的新位置。

拖拽的对象有好几种,包括标签节点、图片、链接、选中的文字等等。在网页中,除了标签节点默认不可以拖拉,其它(图片 <img>、超链接<a>、选中的文字)都可以直接拖拉。

为了让标签节点可拖拉,可以将该标签的 draggable属性设为true

<div class="small" draggable="true">
   可拖动区域
</div>

定义了draggable属性后,就可以给标签定义拖拽事件了。

注意:drag 事件与 mousemove 事件不相容,只能取其一。

1. 被拖拽对象相关事件

拖拽是由拖动与释放两部分组成,拖拽事件也分为:被拖拽对象的相关事件容器的相关事件

  • 被拖拽对象的相关事件

事件 描述
dragstart 用户开始拖动元素时触发。通常在这个事件的监听函数中,指定拖拽的数据
drag 元素正在拖动时触发。拖拉过程中,在被拖拉的节点上持续触发(相隔几百毫秒)
dragend 用户完成元素拖动后触发。不管拖拉是否跨窗口,或者中途被取消,dragend事件总是会触发的。

下面的例子展示,如何动态改变被拖拽节点的背景色。

<div id="box" class="box" draggable="true">
</div>
<script>
    let box = document.getElementById("box");
    box.addEventListener("dragstart",function (e) {
        e.target.classList.add("dragging");
    });
    box.addEventListener("dragend",function (e) {
        e.target.classList.remove("dragging");
    });
</script>

 

div#box 被拖动的时候,会变成黄色背景。拖拽结束的时候,又变回红色背景。

2. 容器相关事件

  • 容器相关事件

事件 描述
dragenter 当被鼠标拖动的对象进入其容器范围内时触发此事件。通常应该在这个事件的监听函数中,指定是否允许在当前节点放下(drop)拖拉的数据。如果当前节点没有该事件的监听函数,或者监听函数不执行任何操作,就意味着不允许在当前节点放下数据。在视觉上显示拖拉进入当前节点,也是在这个事件的监听函数中设置。
dragover 当被拖动的对象在另一对象容器范围内拖动时触发此事件。dragenter事件在进入该节点时触发,然后只要没有离开这个节点,dragover事件会持续触发
dragleave 当被鼠标拖动的对象离开其容器范围时触发此事件
drop 被拖拉的节点或选中的文本,松开鼠标释放到容器节点时,在容器节点上触发。 注意,如果当前节点不允许drop,或者用户按下 ESC 键,取消这个操作,不会触发该事件。 该事件的监听函数负责取出拖拉数据,并进行相关处理

 注意:

  • 默认情况下,浏览器阻止任何东西向HTML元素放置拖拽的发生。

  • 要在容器(可放置区域)设置阻止默认事件 event.preventDefault(),否则 drop 事件不会被触发。

  • 一般阻止默认事件是写在 dragoverdrop 事件上。

下面的例子展示,如何实现将一个节点从当前父节点,拖拉到另一个父节点中。

<div class="dropzone">
    <div id="box" class="box" draggable="true">
        要拖动的div
    </div>
</div>

<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<script>
    let box = document.getElementById("box");
    let dropzone = document.querySelectorAll(".dropzone");
    box.addEventListener("dragstart",function (e) {
        let _box = this;
        // 开始拖拽的时候,让原来的 div 隐藏,要通过延迟代码执行。
        setTimeout(function () {
            _box.style.opacity = 0;
        },0);
    });
    box.addEventListener("dragend",function (e) {
        // 结束拖拽,原来的div恢复显示。
        e.target.style.opacity = 1;
    });

    dropzone.forEach(function (item,index) {
        item.addEventListener("dragenter",function (e) {
            e.target.classList.add("over");
        });
        item.addEventListener("dragover",function (e) {
            // 阻止默认事件
            e.preventDefault();
        }); 
        item.addEventListener("dragleave",function (e) {
            e.target.classList.remove("over");
        });
        item.addEventListener("drop",function (e) {
            e.preventDefault();  // 阻止默认事件
            // 把 div.box放入对应的div.dropzone 中
            e.target.appendChild(box);
        });
    });
</script>

3. drag 事件执行顺序

  1. dragstart (被拖拽元素)

  2. dragenter(容器)

  3. dragover (容器)

  4. dragleave(容器)

  5. drop (容器)

  6. dragend (被拖拽元素)

dragstart 开始,到 dragend 为止,整个过程都在连续触发 drag (被拖拽元素)。如下图所示,仅保留 dragstart、drag、dragend 事件。

 

 4. 案例:拖拽图片文件到页面中

(1)准备

拖拽文件到页面 div.box 标签中。样式自定。

 <div class="box" id="box">
        <span>把文件拖放在这里</span>
    </div>

 

必须给 dragover 添加禁止默认事件代码。

box.addEventListener("dragover",function (e) {
    e.preventDefault();
});

(2)DataTransfer.files

event.dataTransfer.files属性是一个 FileList 对象,包含一组本地文件,可以用来在拖拉操作中传送。如果本次拖拉不涉及文件,则该属性为空的 FileList 对象。

可以遍历 FileList,也可以利用索引获取某个 file ,并获取filename,type,size 等属性。

let box = document.getElementById("box");
box.addEventListener("dragover",function (e) {
    e.preventDefault();
});
box.addEventListener("drop",function (e) {
    e.preventDefault();
    let file = e.dataTransfer.files[0];
    console.info( e.dataTransfer.files )
    console.info( file )
    console.info( file.name )
    console.info( file.type )
    console.info( file.size )
});

可以利用 URL.createObjectURL(file) 静态方法获取 file 的路径。

(3)拖拽单张图片到页面中

box.addEventListener("drop",function (e) {
    e.preventDefault();
    box.innerHTML = "";
    // 获取文件
    let file = e.dataTransfer.files[0];
    // 获取文件 type
    console.info( file.type );
    // 判断文件是否是图片
    if( /image/.test(file.type)){
        console.info("图片");
    }else{
        box.innerHTML = "请拖入一个图片文件,如png,jpg或者gif";
        return false; // 终止函数运行
    }
    // 生成文件路径
    let url = URL.createObjectURL(file);
    // 创建一个 img 标签
    let img = document.createElement("img");
    img.src = url;
    // 把 img 添加到 box 里。
    box.appendChild(img) 
});

(4)拖拽多张图片到页面中

box.addEventListener("drop",function (e) {
    e.preventDefault();
    box.innerHTML = "";
    // 获取文件列表
    let files = e.dataTransfer.files;
    [...files].forEach(function (item,index) {
        // 判断文件是否是图片
        if( /image/.test(item.type)){
            console.info("图片");
            // 生成文件路径
            let url = URL.createObjectURL(item);
            // 创建一个 img 标签
            let img = document.createElement("img");
            img.src = url;
            // 把 img 添加到 box 里。
            box.appendChild(img)
        }else{
            console.info(`文件${index}不是图片`);
        }
    });
});

猜你喜欢

转载自blog.csdn.net/weixin_42703239/article/details/128809385
今日推荐