资讯专栏INFORMATION COLUMN

JS进阶篇4---原生JS实现对元素的拖拽

phoenixsky / 3681人阅读

摘要:原生实现对元素的拖拽一背景介绍此处为铺垫内容,可跳过随着前端的不断发展,各种各样的前端规范和新知识新技术层出不穷,极大地拓展了开发者的操作空间,也大大地提升了用户体验。

原生 JS 实现对 html 元素的拖拽 一、背景介绍

此处为铺垫内容,可跳过】 随着 Web 前端的不断发展,各种各样的前端规范和新知识、新技术层出不穷,极大地拓展了开发者的操作空间,也大大地提升了用户体验。而随着移动端的不断发展,在移动端,人机交互方式发生了很大转变,新的人机交互方式对提供给用户的 “动作” 有了更高要求,例如拖拽功能,就是在移动端会经常接触到的功能。此文就详细地讲解一下,一个简单的拖拽功能的实现(拖拽元素可改变,浏览器窗口边界检测)。

二、知识准备

为了让各位对此文内容有更深刻的掌握,需要掌握如下知识。

1、clientXclientY 属性

clientXclientY ) 事件属性返回当事件被触发时鼠标指针相对于浏览器当前可视窗口的水平(垂直)坐标。
注意:不包括工具栏和滚动条

2、offsetTopoffsetLeft 属性

offsetTop ( offsetLeft ),指的是子元素距离其父元素的上边框(左边框)的偏移量,在不同的浏览器中其值不同,且与父元素的 position 属性( position: static; 除外)有关。在不同浏览以及不同 position 下的具体值,读者可以自行查阅相关资料,因其内容较多,就不展开论述了。

3、clientWidthclientHeight属性

Element.clientWidthElement.clientHeight )属性表示元素的内部宽度,以像素计。该属性包括内边距,但不包括垂直滚动条(如果有)、边框和外边距。该属性值会被四舍五入为一个整数。如果你需要一个小数值,可使用 element.getBoundingClientRect()

4、setCapturereleaseCapture 方法

MDN 对 SetCapture() 函数的说明为:“该函数在属于当前线程的指定窗口里设置鼠标捕获。一旦窗口捕获了 鼠标,所有鼠标输入都针对该窗口,无论光标是否在窗口的边界内。同一时刻只能有一个窗口捕获鼠标。如果鼠标光标在另一个线程创建的窗口上,只有当鼠标键按下时系统才将鼠标输入指向指定的窗口。”

通俗来讲,举个栗子:一只羊被一根有弹性的绳子( SetCapture )拴在木桩,羊可以在绳子可以延展的范围内 随意活动,但永远无法摆脱绳子的束缚。除非有其他因素导致绳子断了(使用了 ReleaseCapture 或点击了其他窗口)。

ReleaseCapture() 用来释放鼠标捕获,当不再需要继续获得鼠标消息就要应该调用 ReleaseCapture() 释放掉,否则别的线程想捕获鼠标事件就会失败。注意:SetCapture()ReleaseCapture() 必须成对出现。

三、实现思路

如果想对元素进行拖拽,那么必须使用三个事件,并且这三个事件的使用顺序不能打乱。

1、onmousedown:鼠标按下事件
2、onmousemove:鼠标移动事件
3、onmouseup:鼠标抬起事件

拖拽的基本原理就是根据鼠标的移动来移动被拖拽的元素。鼠标的移动也就是 x、y 坐标的变化;元素的移动就是元素 position 属性的 topleft 值的改变。当然,并不是任何时候移动鼠标都要造成元素的移动,而应该判断鼠标左键的状态是否为按下状态,是否是在可拖拽的元素上按下的。具体过程如下:

拖拽状态 = false

鼠标在元素上按下之后 {
    拖拽状态 = true
    设置鼠标捕获 
    记录下鼠标的 x,y 坐标
    记录下元素的 x,y 坐标
}

鼠标在元素上移动时 {
    若拖拽状态为 false 就什么也不做
    如果拖拽状态是 true,那么
        元素的 y 坐标 = 现在鼠标 y - 原来鼠标 y + 原来元素 y
        元素的 x 坐标 = 现在鼠标 x - 原来鼠标 x + 原来元素 x
}

鼠标抬起时 {
    拖拽状态 = false
}
四、完整源码



    
    原生JS实现元素拖拽
    



    

注意事项
1、onmousedown 事件中的操作对象为拖拽元素,而 onmousemoveonmouseup 事件中的操作对象为 document,这是因为,点击某物体时,用需要拖拽的对象即可,onmousemoveonmouseup 是全局区域,也就是整个文档通用,应该使用 document 对象而不是被拖拽的对象(否则,采用拖拽对象时物体只能往右方或下方移动)

2、之所以使用 setCapture()releaseCapture(),其目的是为了修复低版本 IE 的 bug。在低版本 IE 下,当我们在要拖动的元素上,按下鼠标按钮拖动时,当拖动过快,或者是超出浏览器的文档窗口时,拖动对象身上的 onmousedown 事件就会失效。在 Chrome 我们可以为 doucment 绑定 onmouseout 事件来判断是否发生这样的情况,但是 IE 下却行不通,所以最好的解决办法就时为要拖动的元素对象锁定鼠标事件,在拖动后再解除事件锁定。在本例中,这两个方法用于 onmousedownonmouseup 中。

3、另外,在 Firefox 中有相似的功能,它们分别是:

captureEvents ( Event.eventType )

releaseEvents ( Event.eventType )

五、案例总结

虽然元素的拖拽算是一个比较基础的知识点,但在实现的过程中,有许多细节需要注意,例如计算坐标的时候,对那几个属性的了解程度,再例如,事件的触发顺序,还有,IE 中的事件获取, setCapture()releaseCapture() 等。

虽然 H5 直接提供了拖拽 API,但为了兼容性,小伙伴们还是需要用 js 去处理的。上例中,虽然对拖拽做了一定的兼容性处理和封装,拖拽对象可以是 div,图片,文字等,但总的来说,是一个比较基础的实现,但有了这个原型,小伙伴们可以根据自己的需求,再加以封装和拓展,例如限定拖拽方向、范围、速度等等。有任何疑问或建议,可以在评论区留言哦,转载请注明出处。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105116.html

相关文章

  • JS进阶4---原生JS实现元素拖拽

    摘要:原生实现对元素的拖拽一背景介绍此处为铺垫内容,可跳过随着前端的不断发展,各种各样的前端规范和新知识新技术层出不穷,极大地拓展了开发者的操作空间,也大大地提升了用户体验。 原生 JS 实现对 html 元素的拖拽 一、背景介绍 【此处为铺垫内容,可跳过】 随着 Web 前端的不断发展,各种各样的前端规范和新知识、新技术层出不穷,极大地拓展了开发者的操作空间,也大大地提升了用户体验。而随着...

    evin2016 评论0 收藏0
  • 前端基础进阶(十):面向象实战之封装拖拽

    摘要:前面几篇文章,我跟大家分享了的一些基础知识,这篇文章,将会进入第一个实战环节利用前面几章的所涉及到的知识,封装一个拖拽对象。不封装对象直接实现利用原生封装拖拽对象通过扩展来实现拖拽对象。 showImg(https://segmentfault.com/img/remote/1460000008699587); 前面几篇文章,我跟大家分享了JavaScript的一些基础知识,这篇文章,...

    Eidesen 评论0 收藏0
  • 从GGEditor的一个案例看JS原生拖拽功能

    摘要:涉及部分的,不会对理解全局产生干扰。在上监听事件,当为画布时,通过创建一个蓝色虚线框移动的时候,更新的位置在上监听事件,落在画布时,创建一个的节点从而完成整个拖拽添加元素的功能。 showImg(https://segmentfault.com/img/remote/1460000019564977);showImg(https://segmentfault.com/img/remot...

    PingCAP 评论0 收藏0
  • 从GGEditor的一个案例看JS原生拖拽功能

    摘要:涉及部分的,不会对理解全局产生干扰。在上监听事件,当为画布时,通过创建一个蓝色虚线框移动的时候,更新的位置在上监听事件,落在画布时,创建一个的节点从而完成整个拖拽添加元素的功能。 showImg(https://segmentfault.com/img/remote/1460000019564977);showImg(https://segmentfault.com/img/remot...

    taowen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<