浏览器拖动API全剖析

媒介

拖动api是HTML5增加的API,供应了元素拖动的原生支撑

拖动API相关于其他的事宜API庞杂了一些,缘由就在于拖动是被拖动元素与被安排元素的互动触及到了两个元素,而不是一个致使流程的庞杂,然则个中的许多设想是有规律可循的.

如今我们来看一个基础的运用场景,这里有两个元素A和B,A是可拖动元素而B是可安排元素,我们将A安排到B中

  1. 鼠标按下后拖动元素A,触发A的dragstart事宜
  2. 最先挪动A元素
  3. 方才触遇到B容器,触发B的dragenter事宜
  4. 挪动到B上方
  5. 触发B容器的dragover事宜,该事宜类似于mouseover事宜是一连触发的
  6. 松开鼠标安排A
  7. 触发B容器的drop事宜
  8. 触发A元素的dragend事宜

基础流程

我们来完成上面的几个步骤

html

<div id="test" draggable="true"></div>


<div id="display">
    目的地区
</div>

注重:被拖动的元素须要设置draggable属性

css

html,
body {
    height: 100%;
}

html,
body,
div {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

#test {
    margin: 0 auto;
    margin-top: 10%;
    width: 50%;
    height: 50%;
    background: #4CB8C4;
    background: linear-gradient(to right, #3CD3AD, #4CB8C4);
    box-shadow: 0 0 15px -3px black;
}

#display {
    margin: 0 auto;
    margin-top: 10%;
    width: 30%;
    height: 30%;
    background-color: rgba(0, 0, 0, 0.055);
}

javascript

let dargElem = document.getElementById('test');
let targetElem = document.getElementById('display');

dargElem.addEventListener('dragstart', (event) => {

    // 被拖动元素最先事宜
    console.log(event);
})

// 拖动完毕事宜
dargElem.addEventListener('dragend', (event) => {

    console.log('拖动完毕事宜');
})

// 进入容器的事宜
targetElem.addEventListener('dragenter', (event) => {

    event.preventDefault();
    console.log('拖动进入事宜');
})

// 悬浮到容器上方的事宜
targetElem.addEventListener('dragover', (event) => {
    
    event.preventDefault();
})

// 拖动事宜
targetElem.addEventListener('drop', (event) => {

    console.log('触发安排事宜')
})

这个例子中dargElem保留的是被拖动元素,我们为他注册了dragstartdragend事宜,
别的一个变量targetElem是容器元素我们为他注册了dragenter dragover drop 事宜

掌握台输出:

最先拖动
拖动进入事宜
触发安排事宜
拖动完毕事宜

注重:这个例子中运用了event.preventDefault()用于阻挠默许的行动,比方拖动a标签的时刻有能够触发默许的跳转行动

一切事宜列表(不包括厂商事宜和浏览器不支撑事宜):

  • 被拖动的对象

    • dragstart 拖动最先触发
    • drag 拖动过程当中触发 一连触发
    • dragend 拖动完毕后触发
  • 被看成容器的元素

    • dragenter 元素进入时刻触发
    • dragover 可拖动元素置于容器元素上方时触发 一连触发
    • drop 可拖动元素置入到容器元素中触发
    • dragleave 可拖动元素挪动出容器元素时刻触发

注重:容器元素肯定须要监听dragover事宜而且一最先挪用event.preventDefault()后续的drop才会触发dragover相称因而一个过滤器,只许可指定的元素能够触发drop事宜

数据的交互

前面说道拖动事宜是两个元素的互动,然则仅仅运用事宜是不够的,我们须要其他的手腕在两个元素之间通报信息

dragstart事宜触发的时刻所供应的event对象中含有一个DataTransfer对象,这个对象许可在多个事宜中保留信息且在一切拖动事宜中存在

简朴信息通报操纵:

  1. 被拖动元素挪用该对象的setData()要领设置值
  2. 容器元素在drop事宜中运用event对象的DataTransfer属性的getData()要领猎取在dragstart事宜中设置的值

例子:

let dargElem = document.getElementById('test');
let targetElem = document.getElementById('display');

dargElem.addEventListener('dragstart', (event) => {

    event.dataTransfer.setData('test',[1,2,3]);
})

// 必需设置
targetElem.addEventListener('dragover', (event) => {
    event.preventDefault();
})

// 拖动事宜
targetElem.addEventListener('drop', (event) => {

    event.preventDefault();
    console.log(event.dataTransfer.getData('test'));
})

能够看到DataTransfer数据的设置就是典范的键值操纵罢了

综合实例一个来自MDN的例子:

html

<div class="dropzone">
    <div id="draggable" draggable="true" ondragstart="event.dataTransfer.setData('text/plain',null)">
        This div is draggable
    </div>
</div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>

css

#draggable {
width: 200px;
height: 20px;
text-align: center;
background: white;
}

.dropzone {
width: 200px;
height: 20px;
background: blueviolet;
margin-bottom: 10px;
padding: 10px;
}

javascript

var dragged;

/* 可拖动的目的元素会触发事宜 */
document.addEventListener("drag", function( event ) {

}, false);

document.addEventListener("dragstart", function( event ) {
  // 保留拖动元素的援用(ref.)
  dragged = event.target;
  // 使其半透明
  event.target.style.opacity = .5;
}, false);

document.addEventListener("dragend", function( event ) {
  // 重置透明度
  event.target.style.opacity = "";
}, false);

/* 放下目的节点时触发事宜 */
document.addEventListener("dragover", function( event ) {
  // 阻挠默许行动
  event.preventDefault();
}, false);

document.addEventListener("dragenter", function( event ) {
  // 当可拖动的元素进入可安排的目的高亮目的节点
  if ( event.target.className == "dropzone" ) {
      event.target.style.background = "purple";
  }

}, false);

document.addEventListener("dragleave", function( event ) {
  // 当拖动元素脱离可安排目的节点,重置其背景
  if ( event.target.className == "dropzone" ) {
      event.target.style.background = "";
  }

}, false);

document.addEventListener("drop", function( event ) {
  // 阻挠默许行动(如翻开一些元素的链接)
  event.preventDefault();
  // 挪动拖动的元素到所挑选的安排目的节点
  if ( event.target.className == "dropzone" ) {
      event.target.style.background = "";
      dragged.parentNode.removeChild( dragged );
      event.target.appendChild( dragged );
  }

}, false);

DataTransfer详解

DataTransfer不单单议用于元素之间信息的通报,同时能够掌握拖动的款式,以及通报分外的信息

属性:

  • dropEffect 范例 String
  • effectAllowed 范例 String
  • files 范例 FileList
  • types 范例 DOMStringList

要领:

  • void addElement(in Element element)
  • void clearData([in String type])
  • String getData(in String type)
  • void setData(in String type, in String data)
  • void setDragImage(in nsIDOMElement image, in long x, in long y)

这里只解说一下dropEffecteffectAllowed由于这里有坑files属性用于从浏览器外部拖入文件时刻运用types运用较少这里不提了

供应MDN链接,看完本文后能够查阅剩下的要领和属性:

https://developer.mozilla.org…

dropEffecteffectAllowed用于掌握拖动的时刻光标角标的款式,过滤差别的范例拖动行动

dropEffect能够的值:

  • copy: 复制到新的位置
  • move: 挪动到新的位置.
  • link: 竖立一个源位置到新位置的链接.
  • none: 制止安排(制止任何操纵).

effectAllowed能够的值:

  • copy: 复制到新的位置.
  • move:挪动到新的位置 .
  • link:竖立一个源位置到新位置的链接.
  • copyLink: 许可复制或许链接.
  • copyMove: 许可复制或许挪动.
  • linkMove: 许可链接或许挪动.
  • all: 许可一切的操纵.
  • none: 制止一切操纵.
  • uninitialized: 缺省值(默许值), 相称于 all.

简朴来讲在被拖动元素的事宜中设置effectAllowed属性示意期待的拖动款式,而在容器元素中设置dropEffect示意容器指定的款式,其他的设置都邑被忽视

关于dropEffect只要在dragover事宜中中修正值才会影响款式,我用的是Chrome66

关于effectAllowed只要在dragstart事宜中有用

例子两边都运用link款式:

let dargElem = document.getElementById('test');
let targetElem = document.getElementById('display');

// 拖动最先事宜
dargElem.addEventListener('dragstart', (event) => {
    event.dataTransfer.effectAllowed = 'link';
})

// 悬浮到容器上方的事宜
targetElem.addEventListener('dragover', (event) => {
    event.dataTransfer.dropEffect = 'link';
    event.preventDefault();
})

// 拖动事宜
targetElem.addEventListener('drop', (event) => {
    console.log('pass')
    event.preventDefault();
})

这个例子中drop事宜被触发

例子effectAllowed设置为copydropEffect设置为link:

let dargElem = document.getElementById('test');
let targetElem = document.getElementById('display');

// 拖动最先事宜
dargElem.addEventListener('dragstart', (event) => {
    event.dataTransfer.effectAllowed = 'link';
})

// 悬浮到容器上方的事宜
targetElem.addEventListener('dragover', (event) => {
    event.dataTransfer.dropEffect = 'link';
    event.preventDefault();
})

// 拖动事宜
targetElem.addEventListener('drop', (event) => {
    console.log('pass')
    event.preventDefault();
})

这个例子实行的效果就是拖动时刻的角标一直是制止标记,在容器元素上松开也不会触发drop事宜

参考链接

https://developer.mozilla.org…

https://developer.mozilla.org…

https://blog.csdn.net/baidu_3…

    原文作者:ASCll
    原文地址: https://segmentfault.com/a/1190000015938130
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞