H5 拖放 - 学习

前言

一个典型的drag操作是这样开始的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发

第一部分 在拖动元素上

要使其他的 HTML 元素可拖动,必须做三件事:

  • 在你想要拖动的元素上,将 draggable 属性设置成 true
  • 为事件添加一个监听器 dragstart
  • 在上面定义的监听器中设置拖动数据

1.1 draggable: 可拖动属性

  • draggable: 全局属性, 是一个枚举类型, 而不是布尔类型. 这意味着必须显式指定值为 true 或者 false ,像 这样的简写是不允许的。正确的用法是`
  • 默认情况下,只有已选中的文本、图片、链接可以拖动。对其它的元素来说,必须按拖动机制的顺序设置 ondragstart 事件才能正常工作
  • 属性 draggable 设置为 true,所以这个元素变成可拖动的。如果该属性被省略或被设置为 false,则该元素将不会被拖动,而是只选中文本。
  • 注意,当一个元素被设置成可拖动的时候, 文本或者其中的其他元素不能再以正常的方式(通过鼠标点击和拖动)被选择。用户必须按住 alt 键,用鼠标选择文本,或者使用键盘来代替。
    
    

1.2 ondragstart: 开始拖动事件

  • 当用户开始拖动时,会触发 dragstart 事件(此事件会冒泡),
  • 所有拖拽事件都有一个名为 dataTransfer的属性,它持有拖曳数据(dataTransfer 是一个 DataTransfer 对象)。
  • 一个web应用需要添加拖拽功能时,应当仅仅使用DragEvent(事件对象)和DataTransfer(事件对象中的属性)接口即

DataTransfer对象

这个对象可以从所有拖动事件 drag eventsdataTransfer属性上获取,但是不能单独创建。

详情见MDN资料

  • 属性:

    • dropEffect: 影响到拖动过程中浏览器显示的鼠标样式
  • 方法:

    • setData: 设置拖动数据
    /**
           * @name: 设置拖动元素的数据
           * @param {type: 数据MIME} 
           * @param {value: 数据值} 
           * @return: none
    */
    event.dataTransfer.setData(type, value);
    
    // =============== 示例 ==============
    /*
        * type类型: 
            application/x-bookmark: 自定义类型
            text/uri-list: URL
            text/plain: 文本
        * 您可以以多种格式提供数据, 每种格式可以提供一次, 如果您试图以相同的格式添加两次数据,那么新的数据将替换旧的数据。
        * 不能设置复杂类型数据, 此时可以通过反序列化解决
    */
    var dt = event.dataTransfer;
    dt.setData("application/x-bookmark", bookmarkString);
    dt.setData("text/uri-list", "http://www.mozilla.org");
    dt.setData("text/plain", "http://www.mozilla.org");
    
    • getData(): 获取设置的数据
    /**
             * @name: 获取通过setData()设置的数据
             * @param {type: 数据MIME} 
             * @return: none
    */
    event.dataTransfer.clearData(type);
    
    /*
      * 参数必填, 没有参数会直接报错
      * 当参数的 MIME 没有对应值时, 返回空字符串
    */
    event.dataTransfer.getData("text/plain");
    
    • clearData: 清除数据**
    /**
           * @name: 清除拖动元素的数据
           * @param {type?: 数据MIME} 
           * @return: none
    */
    event.dataTransfer.clearData(type);
    
    // ================ 示例 ==================
    /*
        * 如果没有参数调用此方法,或者格式为空 ,则将删除所有类型的数据。
        * 该方法只能在dragstart 事件的处理程序中使用,因为这是拖动操作的数据存储只能写入的时间。
        * 
    */
    event.dataTransfer.clearData("text/uri-list");
    
    • setDragImage(): 设置拖动反馈图像

    当一个拖动发生时,一个半透明的图像是由拖拽目标生成的("dragstart" 事件被触发的元素),并在拖动过程中跟踪鼠标指针。这个映像是自动创建的,所以你不需要自己创建它。但是,您仍然可以使用 setDragImage() 方法来自定义拖动反馈图像。

    /**
           * @name: 设置拖动反馈图像
           * @param {image: 图像的引用, 通常是图像元素, 也可以是画布(canvas) 或任何其他元素}
           * @param {xOffset: 相对于图片的横向偏移量}
           * @param {yOffset: 相对于图片的纵向偏移量}
           * @return: none
    */
    event.dataTransfer.setDragImage(image, xOffset, yOffset);
    
    // ============== 示例 ===========
    /*
        * 引用通常是一个图像元素,但它也可以是画布(canvas)或任何其他元素。
    */
    var canvas = 
    document.createElementNS("http://www.w3.org/1999/xhtml","canvas");
    canvas.width = canvas.height = 50;
    
    var ctx = canvas.getContext("2d");
    ctx.lineWidth = 4;
    ctx.moveTo(0, 0);
    ctx.lineTo(50, 50);
    ctx.moveTo(0, 50);
    ctx.lineTo(50, 0);
    ctx.stroke();
    
    var dt = event.dataTransfer;
    dt.setData('text/plain', 'Data to Drag');
    dt.setDragImage(canvas, 25, 25);
    

第二部分 放置目标

web页面或应用程序的大多数区域都不是 drop 数据的有效位置。因此,这些事件的默认处理是不允许出现 drop。

如果您想要允许 drop,您必须通过取消事件来防止默认的处理, 在 dragover 事件中调用 preventDefault() 方法将表明在该位置允许 drop 。

1. dragover: 当元素或选中的文本被拖到一个可释放目标上时触发(每100毫秒触发一次)。

在 dragover 事件中调用 preventDefault() 方法, 但是这样的话, 会将所有拖动元素放置进来, 通常希望只在某些情况下调用 preventDefault() 方法, 这时可以通过检查拖放元素的 dataTransfer 的types属性(而使用ev.dataTransfer.getData("text/plain") 这种方式无用, 因为在dragover事件中无法获取到数据的)

  • types属性: 拖动操作中使用的数据格式数组。每种格式都是字符串类型。如果拖动操作不包含数据,则此数组列表将为空。如果拖动操作中包含任何文件,则其中一个类型将是Files。

    特别注意: 这是一个只读属性, 如果通过enent.dataTransfer.types直接查看数据

    // 可以通过判断 types 中存放的数据类型来判断是否是需要的拖动元素 (因为图片, 链接也是默认可以拖动的) -- form/item(可以自定义类型的)
        if ([...e.dataTransfer.types].includes("form/item")) {
          e.preventDefault();
        }
    

2. drop: 拖动元素放置的时候触发

处理放置效果, 在drop事件中处理, 在这个事件中可以调用event.dataTransfer.getData()来获取数据

注意每个处理程序调用 preventDefault() 来阻止对这个事件的其它处理过程(如触点事件或指针事件)

// 拖动第四步: 在拖动元素放置到 放置目标 , 执行一系列的操作
  // drop事件: 当元素或选中的文本在可释放目标上被释放时触发
  box.addEventListener("drop", function(e) {
    console.log(e.dataTransfer.getData("form/item"));
    e.preventDefault();
    this.innerText = e.dataTransfer.getData("form/item");
  });

第三部分 简单实例



  
    
    
    
    Document
    
  
  
    
    

最后

只是简单学习了一下H5的拖放过程, 没有深入的细究, 还有好多事件 和 属性在一定的场景下有作用的

参考资料

  • MDN
  • 菜鸟教程

你可能感兴趣的:(H5 拖放 - 学习)