ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端页面元素拖动

2021-06-10 14:04:38  阅读:240  来源: 互联网

标签:鼠标 拖动 前端 元素 mousemove mousedown position 页面 target


最近工作不是很忙,所以借这个时间整理一下之前遇到的问题,记录一下相关的解决方案。

首先整理一下页面元素拖动实现的思路:

  1. 由于页面上可拖动的元素数量是不固定的,所以不应该把事件监听函数绑定到每个元素上,可以使用事件代理,将事件监听函数绑定到父级元素上。
  2. 移动位置的计算有2种思路,第一种是在mousedown事件触发时,记录鼠标事件的位置和元素的位置,然后mousemove事件每次触发,用当前的鼠标事件位置减mousedown事件的鼠标位置,移动的距离,再加上mousedown事件触发时记录的元素左边和上边的距离,即可计算出新的位置,简单地说就是鼠标每次移动后的位置与鼠标初始位置比较,得出移动的距离。第二种就是每次mousemove事件触发,都与上一次的位置进行比较;这种方法算起来比较麻烦,所以我采用第一种计算方法。
  3. 具体计算方法是这样的,在mousedown触发后,记录鼠标的位置,即e.clientX,e.clientY,以及元素距离左边和上边的距离,e.target.offsetLeft和e.target.offsetTop,因为我将父级元素的position设为relative,所以这两个值是元素边框外侧到父元素边框内侧的距离,在mousemove触发时,记录鼠标的新位置,即e.clientX,e.clientY,然后用 鼠标新位置 - 鼠标初始位置 + 元素初始左、上距离 算出新的位置,然后将元素position设为absolute,计算出的值即为left和top的值。
  4. 有2个需要注意的地方,第一,mousemove事件与mousedown,mouseup2个并不是连续的事件,当鼠标移动至少1个像素时,mousemove事件就会触发,与鼠标是否按下无关,所以需要在事件处理函数中校验拖动的元素是否为同一个对象;第二,还是因为mousemove事件与mousedown,mouseup2个并不是连续的事件,必须要保证mousemove事件是在mousedown事件后触发的,即鼠标按下,然后移动,不能是,鼠标按下,鼠标松开,然后移动。对于这两个问题,解决思路是一致的,都是在父级作用域中定义变量来控制,对于第一个问题,在mousedown事件触发后,将目标元素对象赋值给定义好的变量,然后在mousemove事件中校验事件对象元素是否为同一个元素,对于第二个问题,在父级作用域中定义一个flag,当mousedown触发,设为true,mouseup触发,设为false,在mousemove触发,校验是否为true就行了。

示例代码如下:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3   <head>
 4     <meta charset="UTF-8" />
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
 6     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 7     <title>Document</title>
 8     <style>
 9       .rect {
10         width: 100px;
11         height: 100px;
12         background-color: #eee;
13         margin: 5px;
14       }
15       .box {
16         position: relative;
17       }
18     </style>
19   </head>
20   <body>
21     <div class="box">
22       <p class="rect"></p>
23       <p class="rect"></p>
24       <p class="rect"></p>
25       <p class="rect"></p>
26       <p class="rect"></p>
27       <p class="rect"></p>
28       <p class="rect"></p>
29       <p class="rect"></p>
30       <p class="rect"></p>
31       <p class="rect"></p>
32       <p class="rect"></p>
33       <p class="rect"></p>
34       <p class="rect"></p>
35     </div>
36 
37     <script>
38       let position = {
39         x: 0,
40         y: 0,
41         left: 0,
42         top: 0,
43       }
44       let target = null
45       isDown = false
46       let box = document.querySelector(".box")
47       box.addEventListener("mousedown", function (e) {
48         if (!e.target.className.includes("rect")) return
49         target = e.target
50         position.x = e.clientX
51         position.y = e.clientY
52         position.left = e.target.offsetLeft
53         position.top = e.target.offsetTop
54         isDown = true
55       })
56 
57       box.addEventListener("mousemove", function (e) {
58         if (!e.target.className.includes("rect")) return
59         if (!isDown) return
60         target.style.position = "absolute"
61         let mx = e.clientX
62         let my = e.clientY
63         let myLeft = mx - position.x + position.left
64         let myTop = my - position.y + position.top
65 
66         console.log({ myLeft, myTop })
67         target.style.left = myLeft + "px"
68         target.style.top = myTop + "px"
69       })
70       box.addEventListener("mouseup", function (e) {
71         if (isDown) isDown = false
72       })
73     </script>
74   </body>
75 </html>

 

标签:鼠标,拖动,前端,元素,mousemove,mousedown,position,页面,target
来源: https://www.cnblogs.com/KlllB/p/14870762.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有