JavaScript进阶之实现拖拽(上)

落落落洛克 等级 647 0 0
标签: Javascript

我的前端学习笔记📒

最近花了点时间把笔记整理到语雀上了,方便童鞋们阅读

JavaScript进阶之实现拖拽(上)

JavaScript进阶之实现拖拽(上)

最近做到的react项目就有一个拖拽的需求,然后大概搜索了一下,找到了star比较高的react-dnd库,但是阅读react-dnd的官方文档还是有点难受的,因为概念性比较强,所以在介绍react-dnd之前我们来实现原生拖拽

原生实现拖拽

Mouse事件实现拖拽

在h5之前,原生实现拖拽是根据Mouse事件来实现的,需要用到以下这三个事件mousedown,mouseup,mousemove

  • mousedown 事件在指针设备按钮按下时触发。
  • mouseup事件在指针设备按钮抬起时触发。
  • 当指针设备( 通常指鼠标 )在元素上移动时, mousemove 事件被触发。

JavaScript三大家族

JavaScript进阶之实现拖拽(上)
JavaScript进阶之实现拖拽(上)

明白了上述👆三个事件方法的作用以及JavaScript三大家族,我们来实现个简单版的拖拽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <img id="ball" src="https://js.cx/clipart/ball.svg" alt="">
    <script>
       const ball=document.querySelector("#ball")
       ball.onmousedown = function(event{
       let shiftX = event.clientX - ball.getBoundingClientRect().left;
       let shiftY = event.clientY - ball.getBoundingClientRect().top;
        ball.style.position = 'absolute';
        ball.style.zIndex = 1000;
        document.body.append(ball);
        moveAt(event.pageX, event.pageY);
        // 移动现在位于坐标 (pageX, pageY) 上的球
        // 将初始的偏移考虑在内
        function moveAt(pageX, pageY{
        ball.style.left = pageX - shiftX + 'px';
        ball.style.top = pageY - shiftY + 'px';
        }
        function onMouseMove(event{
        moveAt(event.pageX, event.pageY);
        }
        // 在 mousemove 事件上移动球
        document.addEventListener('mousemove', onMouseMove);
        // 放下球,并移除不需要的处理程序
        ball.onmouseup = function({
        document.removeEventListener('mousemove', onMouseMove);
        ball.onmouseup = null;
        };
        };
        ball.ondragstart = function({
        return false;
    };
    
</script>
</body>
</html>

效果如下:

JavaScript进阶之实现拖拽(上)

注意

ball.ondragstart = function({
  return false;
};

如果不设置这段代码,会发生奇怪的现象,这是因为浏览器有自己的对图片和一些其他元素的拖放处理,会在我们拖放时自动运行,这与我们的拖放处理产生了冲突。

HTML 拖放(Drag and Drop)

拖拽事件

HTML 的 drag & drop 使用了 DOM event model 以及从mouse events 继承而来的 drag events 。一个典型的drag操作是这样开始的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发(比如drag 和 dragover 事件类型)

JavaScript进阶之实现拖拽(上)
  • drag: 拖拽源
  • drop:拖拽源最终放置的目标
  • DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。
  • draggable 属性:就是标签元素要设置draggable=true
  • ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上
  • ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上
  • ondragover 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上
  • ondrop 事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
  • ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上
  • Event.preventDefault()方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。
    Event.effectAllowed 属性:就是拖拽的效果。

注意理解上述👆的概念有注意理解react-dnd库的api

举个例子🌰:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />

    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      body {
        font16px Arial, Helvetica, sans-serif;
      }
      li {
        width:200px;
        height40px;
        text-align: center;
        line-height40px;
        border:1px dashed #cccccc
        cursor: pointer;
        user-select: none;
        background-color: white;
        list-style: none;
      }
      .more {
        border-top1px dotted rgb(196, 196, 196);
        font-size12px;
        padding-top10px;
      }
      .more,
      .more a {
        colorrgb(96, 96, 96);
      }
    
</style>
  </head>
  <body>
    <ul>
      <li
        draggable="true"
        ondragend="dragEnd()"
        ondragover="dragOver(event)"
        ondragstart="dragStart(event)"
      >

        Apples
      </li>
      <li
        draggable="true"
        ondragend="dragEnd()"
        ondragover="dragOver(event)"
        ondragstart="dragStart(event)"
      >

        Oranges
      </li>
      <li
        draggable="true"
        ondragend="dragEnd()"
        ondragover="dragOver(event)"
        ondragstart="dragStart(event)"
      >

        Bananas
      </li>
      <li
        draggable="true"
        ondragend="dragEnd()"
        ondragover="dragOver(event)"
        ondragstart="dragStart(event)"
      >

        Strawberries
      </li>
    </ul>
    <script>
      var selected;
      const li = document.createElement("li");
      function dragOver(e{
        // 向前拖拽 向后拖拽
        // 拖动目标(drop)是不是在拖拽源(drag)的前面
        if (isBefore(selected, e.target)){         
           e.target.parentNode.insertBefore(selected, e.target);
        }else {e.target.parentNode.insertBefore(selected, e.target.nextSibling);}
      }

      function dragEnd({
        selected = null;
      }

      function dragStart(e{
        selected = e.target;
        console.log(selected)
      }

      function isBefore(el1, el2{
        var cur;
        if (el2.parentNode === el1.parentNode) {
          for (cur = el1.previousSibling; cur; cur = cur.previousSibling) {
            if (cur === el2) return true;
          }
        } else return false;
      }
    
</script>
  </body>
</html>

效果图:

JavaScript进阶之实现拖拽(上)

是不是很接近我们的需求啦

自定义拖动图像

拖动过程中,浏览器会在鼠标旁显示一张默认图片。当然,应用程序也可以通过 setDragImage() 方法自定义一张图片,如下面的例子所示。

 function dragStart(e{
        selected = e.target;
        dragstart_handler(e)
        // 延时是为了浏览器能生成拖拽图片
        setTimeout(()=>{
          selected.style.opacity='0'
        },0)
      }
   function dragstart_handler(ev{
      var img = new Image(); 
      img.src = 'https://js.cx/clipart/ball.svg'
      ev.dataTransfer.setDragImage(img, 1010);
     }
JavaScript进阶之实现拖拽(上)

定义拖动效果

dropEffect 属性用来控制拖放操作中用户给予的反馈。它会影响到拖动过程中浏览器显示的鼠标样式。比如,当用户悬停在目标元素上的时候,浏览器鼠标也许要反映拖放操作的类型。

有 3 个效果可以定义:

  • copy 表明被拖动的数据将从它原本的位置拷贝到目标的位置。
  • move 表明被拖动的数据将被移动。
  • link 表明在拖动源位置和目标位置之间将会创建一些关系表格或是连接。

参考:MDN HTML5 drag & drop 拖拽与拖放简介

我的前端学习笔记📒

最近花了点时间把笔记整理到语雀上了,方便童鞋们阅读

JavaScript进阶之实现拖拽(上)

JavaScript进阶之实现拖拽(上)

收藏
评论区

相关推荐

JavaScript进阶之实现拖拽(上)
我的前端学习笔记📒 最近花了点时间把笔记整理到语雀上了,方便童鞋们阅读 我的前端学习笔记📒(https://www.yuque.com/wanggangfeng
javascript实践教程-01-javascript介绍
本节目标1. 了解javascript是什么。2. 了解javascript能干什么。 内容摘要本篇介绍了javascript是什么,为什么要用javascript,ECMAScript标准是什么等。阅读时间大约510分钟。 javascript是什么?javascript是世界上最流行的脚本语言,因为你在电脑、手机、平板上浏览的所有的网页,以及无数基于HT
javascript实践教程-02-javascript入门
本节目标1. 掌握如何编写javascript代码。2. 掌握javascript的3个弹框。3. 掌握javascript的注释。4. 掌握浏览器的调试工具控制台。 内容摘要本篇介绍了如何在网页上编写js代码,如何引入外部js代码文件,js的3个弹框、注释语法,还有浏览器调试工具的控制台使用。阅读时间1520分钟。 script标签如果我们需要在网页中编写
2018年 JavaScript 明星项目
![](https://oscimg.oschina.net/oscnet/c52a3381-8d56-4509-a191-4dd76ca37bb3.jpg)在 2016年 和 2017年 之后,欢迎来到第三届 JavaScript 明星项目! 是时候回顾 2018 年 Javascript 领域的发展与变化了。 通过对比各项目过去 12 个月在 Git
2018年 JavaScript 明星项目
![](https://oscimg.oschina.net/oscnet/c52a3381-8d56-4509-a191-4dd76ca37bb3.jpg)在 2016年 和 2017年 之后,欢迎来到第三届 JavaScript 明星项目! 是时候回顾 2018 年 Javascript 领域的发展与变化了。 通过对比各项目过去 12 个月在 Git
JavaScript 踩坑心得— 为了高速(下)
#####**一.前言** 本文的上一篇 [JavaScript 踩坑心得— 为了高速(上)](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fnews.oneapm.com%2Fbi-javascript%2F) 主要和大家分享的是 JavaScript 使用过程中的基本原则以及编写过程中的
JavaScript 非常重要的几个概念
JavaScript是一门比较复杂的语言。如果你是一名JavaScript开发人员,不管处于什么样的水平,都有必要了解JavaScript的基本概念。小编最近的工作涉及到JavaScript,于是本文就介绍了几个非常重要的 JavaScript 概念,但绝对不是说JavaScript 开发人员只需要知道这些就可以了。 01-变量赋值(值与引用) Java
JavaScript之函数
      玩js自然要和函数打交到。函数嘛简单来说就是给代码分个块,方便调用、信息隐藏和代码复用,还可以用于指定对象的行为。另外函数还可以玩出很多花样来。。。 JavaScript 使用关键字 function定义函数。 定义一个函数: //函数声明 //这种定义函数的好处是可以在当前作用域内任何位置调用,因为变量的声明和函数的
Javascript解析机制 执行机制
HTML5学堂:在学习JavaScript过程中,我们需要了解事件的机制是怎么执行的?本文将会提到JavaScript事件机制的解析,希望对大家有帮助! javascript解析的过程主要分为两个阶段,分别是编译与执行阶段。 在编译期,javascript解释器将完成对javascript代码的预处理,即将javascript代码转换为字节码。 在执行
Node.js
1.Node来历 --------     2009年,正是推出基于Javascript语言和V8引擎的开源Web服务项目,命名为Node.js,Node.js是第一次把Javascript带到后端开发。全很很多开发人员都熟悉Javascript,所以Node.js一下子就火了。     Javascript语言本身是完善的函数式语言,在前端开发时,开发
Node.js 简单学习
明白 JavaScript 语言,你就会用 Node.js 了。最常见的运行 JavaScript 语言的地方就是用户的浏览器,几乎所有的浏览器上都有个 JavaScript 引擎,这个引擎负责运行在页面中嵌入的 JavaScript 代码。代码是在用户的浏览器上运行的,用户那头叫前端(Frontend),服务器这头叫后端(Backend)。Node.js
Node.js简介及如何学习Node.js
本文介绍Node.js的诞生史以及如何学习Node.js。 Node.js简史 --------- 从Node.js的命名上可以看到,Node.js的官方开发语言是JavaScript。之所以选择使用JavaScript,显然与JavaScript的开发人员多有关。总所周知,JavaScript是伴随着互联网的发展而火爆起来的,JavaScript也是前
Python 与 Javascript 之比较
最近由于工作的需要开始开发一些Python的东西,由于之前一直在使用Javascript,所以会不自觉的使用一些Javascript的概念,语法什么的,经常掉到坑里。我觉得对于从Javascript转到Python,有必要总结一下它们之间的差异。 ### **基本概念** [Python](https://www.oschina.net/action/G
TypeScript 教程
TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。安德斯·海尔斯伯格,C#的首席架构师,已工作于TypeScript的开发。\[1\] TypeScript扩展了JavaScript的句法,所以任何现有的JavaScript程序可以不
Typescript 和 Javascript之间的区别
JavaScript 和 TypeScript 的概要介绍 ============================= **JavaScript** -------------- JavaScript 是一种轻量级的解释性脚本语言,可嵌入到 HTML 页面中,在浏览器端执行,能够实现浏览器端丰富的交互功能,为用户带来流畅多样的用户体验。 JavaScr