重温---HTML5高级---拖放API

  Drag:拖动

      Drop:释放

  在HTML5之前只能使用鼠标事件模拟出拖放效果;HTML5专门为拖放提供了7个事件句柄。

       

  (1)拖动的源对象(source)可以触发的事件:

       dragstart:拖动开始

       drag:拖动进行中

       dragend:拖动结束

       源对象的拖动过程:dragstart x 1 + drag x n + dragend x 1

       练习:实现一个可以随着鼠标拖动而移动的小飞机

  (2)拖动的目标对象(target)可以触发的事件:

       dragenter:拖动着进入

       dragover:拖动着在目标对象上方

       dragleave:拖动着离开

       drop:松手/释放/松开

       目标对象的进入/离开过程:

              dragenter x 1 + dragover x n + dragleave x 1

       目标对象的进入/释放过程:

              dragenter x 1 + dragover x n + drop x 1

  注意:必须阻止dragover的默认行为!否则drop事件无法触发

练习:

(1)垃圾桶初始时半透明;拖动小飞机进入垃圾桶变为不透明,离开后重新半透明,在垃圾桶上方松手也变为半透明。

提示:需要用到目标对象的四个事件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    body{
      text-align: center;
    }
    .half-opacity{
      opacity:0.3;
    }
  </style>
</head>
<body>
  <h3>拖放API---拖放事件的目标对象</h3>
  <img src="./img/trash.png" alt="" id="trash" class="half-opacity">
  <hr>
  <img src="./img/p3.png" alt="" id="p3">
  <script>
    //目标对象可以触发的事件
    trash.ondragenter=function () {
      trash.className='';
    }
    trash.ondragover=function (e) {
      //dragover事件的默认行为,触发dragleave,而跳过drop
      e.preventDefault();
    }
    transh.ondragleave=function () {
      trash.className='half-opacity';
    }
    transh.ondrop=function () {
      trash.className='half-opacity';
    }
  </script>
</body>
</html>

(2)一个垃圾桶,下方有一个容器(div#container),其中有三个小飞机,拖动某个小飞机到垃圾桶上方,则容器中删除此小飞机 

提示:需要用到源对象和目标对象的多个事件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    body{
      text-align: center;
    }
    .half-opacity{
      opacity:0.3;
    }
  </style>
</head>
<body>
  <h3>拖放API---拖放删除效果</h3>
  <img src="./img/trash.png" alt="" id="trash">
  <hr>
  <div id="container">
    <img src="./img/p3.png" alt="">
    <img src="./img/p4.png" alt="">
    <img src="./img/p5.png" alt="">
  </div>
  <script>
    var srcObj=null;  //全局变量,要删除的源对象
    //源对象可以触发的事件
    var list=container.querySelectorAll('img');
    for(var i=1;i<list.length;i++){
      var p=list[i];
      //源对象刚一拖动,记录拖动事件的源对象
      p.ondragstart=function () {
        srcObj=this; //记录拖动的源对象
      }
    }
    //目标对象可以触发的事件
    trash.ondragover=function(e){
      e.preventDefault(); //使得drop可以触发
    }
    trash.ondrop=function () {
      //从父容器中删除拖动的小飞机
      container.removeChild(srcObj);
    }
  </script>
</body>
</html>

如何在拖动的源对象和目标对象间传递数据

  如何在7个事件间传递数据?

  源对象事件——3个:

  目标对象事件——4个:

  (1)方法一:使用全局变量 —— 全局对象污染

  (2)方法二:使用拖放事件对象的dataTransfer属性

  说明:dataTransfer,用作数据传递/转移,看作拖拉机

  源对象触发事件时保存k-v数据:

       src.onxxx = function(e){

              e.dataTransfer.setData( 'key',  'value' );

       }

  目标对象触发事件时获取k-v数据:

       target.onxxx = function(e){

              var value = e.dataTransfer.getData( 'key' )

       }

上述练习(2)代码优化:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    body{
      text-align: center;
    }
    .half-opacity{
      opacity:0.3;
    }
  </style>
</head>
<body>
  <h3>拖放API---拖放删除效果</h3>
  <img src="./img/trash.png" alt="" id="trash">
  <hr>
  <div id="container">
    <img id="p3" src="./img/p3.png" alt="">
    <img id="p4" src="./img/p4.png" alt="">
    <img id="p5" src="./img/p5.png" alt="">
  </div>
  <script>
    //不使用全局变量
    //源对象可以触发的事件
    var list=container.querySelectorAll('img');
    for(var i=1;i<list.length;i++){
      var p=list[i];
      //源对象刚一拖动,记录拖动事件的源对象
      p.ondragstart=function (e) {
        e.dataTransfer.setData('ImgId',this.id)
      }
    }
    //目标对象可以触发的事件
    trash.ondragover=function(e){
      e.preventDefault(); //使得drop可以触发
    }
    trash.ondrop=function () {
      //从父容器中删除拖动的小飞机
      //获取源对象传递的数据
      var id=e.dataTransfer.getData('ImgId');
      var img=document.getElementById(id);
      container.removeChild(img);
    }
  </script>
</body>
</html>

课后练习: 英雄选择

要求:

       拖动某架飞机到目标区域,则在上方显示出该飞机;下方该飞机图消失;替换选中区域已有的飞机。

       拖动另一架飞机到目标区域,则显示出该飞机,之前选中的飞机变为重新回到待选区域。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    body{
      text-align: center;
    }
    #chosen{
      border:1px solid #aaa;
      border-radius:5px;
      padding:10px;
      width:220px;
      margin:0 auto;
    }
    #list{
      background:#f0f0f0;
      min-height: 200px;
      padding:50px;
    }
  </style>
</head>
<body>
  <h3>作业---英雄选择</h3>
  <div id="chosen">
    <img id="p0" src="./img/p0.png" alt="">
  </div>
  <hr>
  <div id="list">
    <img id="p3" src="./img/p3.png" alt="">
    <img id="p4" src="./img/p4.png" alt="">
    <img id="p5" src="./img/p5.png" alt="">
  </div>
  <script>
    //拖动的源对象
  var planes=list.querySelectorAll('img');
  for(var i=0;i<planes.length;i++){
    var p=planes[i];
    p.ondragstart=function (e) {
      //记录拖动的源对象的id,传递给目标对象上
      e.dataTransfer.setData('PlaneID',this.id);
    }
    p.ondrag=function () {
      
    }
    p.ondragend=function () {
      
    }
    //释放的目标对象---div#chosen
    chosen.ondragenter=function () {
      
    }
    chosen.ondragover=function (e) {
      e.preventDefault();
    }
    chosen.ondragleave=function () {
      
    }
    chosen.ondrop=function (e) {
      //隐藏问号飞机p0
      p0.style.display='none';
      //检查除了p0外是否还有其他飞机
      if(chosen.children.length>1){
        //把p0的兄弟移到下方列表中
        list.appendChild(p0.nextElementSibling);
      }
      //拖动的小飞机在chosen上方释放
      var pid=e.dataTransfer.getData('PlaneID');
      var p=document.getElementById(pid);
      chosen.appendChild(p);
    }
    //释放的目标对象---div#list
    list.ondragenter=function () {
      
    }
    list.ondragover=function (e) {
      e.preventDefault();
    }
    list.ondragleave=function () {

    }
    list.ondrop=function (e) {
      //把被拖动的飞机放到列表中
      var pid=e.dataTransfer.getData('PlaneID');
      var p=document.getElementById(pid);
      list.appendChild(p);
      //显示出隐藏的p0
      p0.style.display='block';
    }
  }
  </script>
</body>
</html>

拓展:如何在服务器端下载的网页中显示客户端图片?

  一般情况下,网页只能显示服务器上的图片;

  HTML5中,可以实现用户拖拽一张本地的图片显示在服务器端下载的网页中。

  container.ondrop = function(e){

      var f0 = e.dataTransfer.files[0];

       var reader = new FileReader();

       reader.readAsDataURL(f0);

       reader.onload = function(){

              ///读取完成,数据在reader.result中

       }

  }

HTML5中提供的用于文件输入输出(I/O)的对象:

File:代表一个文件/目录对象

FileList:代表一个文件列表(类数组对象)

FileReader:用于从文件中读取内容

FileWriter:用于向向文件写出内容

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    #container{
      border:1px solid #aaa;
      padding:10px;
      margin:10px;
      min-height: 300px;
      width:300px;
    }
  </style>
</head>
<body>
  <h3>请拖拽您选择的头像到下方区域中</h3>
  <div id="container">

  </div>
  <script>
    //拖放的目标对象---document,监听drop事件,防止浏览器中打开客户端对象
    document.ondragover=function(e){
      //阻止dragover的默认行为,继续触发dragleave
      e.preventDefault();
    }
    document.ondrop=function (e) {
      //阻止document的drop事件默认行为:在当前窗口.中打开客户端图片
      e.preventDefault();
    }
    //拖放的源对象---客户端的一张图片
    //拖放的目标对象---div#container,若图片释放此元素上方,则需要在其中显示出该图片
    container.ondragover=function (e) {
      e.preventDefault();
    }
    container.ondrop=function (e) {
      //读取拖放进来的客户端图片内容
      //chrome此处的显示有问题:files.length:0 其实不是0
      // var list=e.dataTransfer.files;
      // for(var i=0;i<list.length;i++){
      //   var f=list[i];
      // }
      var f0=e.dataTransfer.files[0];  //file
      var reader=new FileReader();  //文件读取器
      //读取指定文件中的内容,作为"数据url"
      reader.readAsDataURL(f0);
      reader.onload=function () {
        console.log(reader.result); //读取的结果
        var img=new Image();
        img.src=reader.result;
        container.appendChild(img);
      }
    }

  </script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_32054169/article/details/83011527