Summary of difficulties in youth Camp project — diagram of the core principle of dragging
An overview of the
Although there are many similar plugins, but in order to study the principle of going to or is implemented by oneself, hope that through this practice can make sense of principle First probably know about the principle of positioning related, in order to facilitate understanding, I spent some time to do the artwork, identifies the key location information represents what
The figure above clearly shows the coordinates to the left and above of the current element distance
style
Position: Fixed is used to position the window, left and top control the position, width and height control the element width and height
Drag-and-drop movement JS principle
Implementation steps:
- Find the distance between the mouse click and the edge of the div element
deltaX
- Mouse position minus
deltaX
Find the distance left of the div element from the left side of the browser
Analysis:
Since clicking on any position in the div can drag the position, but the coordinate of the div is determined by the left, which is the distance between the edge of the div and the left side of the browser window, it is necessary to calculate the distance between the click event and the left side of the div. This distance is the relative distance of the mouse pointer to the div, which remains unchanged during movement. Then subtract this distance from e. clientx to get the left distance after the move, since e. clientx is the distance from the current mouse position to the left of the browser window. The same principle can be used to calculate the distance of top
Avoid dragging any element to move
Determine if e.target’s class is a title bar or body, if not, do not drag
Q: Why bind document to mousemove instead of the current element?
Because if you bind mousemove to the current element, the mouse only works when it moves over the current element, and it doesn’t work when it moves over the current element
The core code is as follows:
el.onmousedown = function (e) {
var disx = e.clientX - el.offsetLeft
var disy = e.clientY - el.offsetTop
// console.log(e.target)
// console.log(e.target.className)
const className = e.target.className
if (["window-body body"."bar"."title"].includes(className)) {
document.onmousemove = function (e) {
const end = new Date().getTime()
if (end - start > 100) {
el.style.left = e.clientX - disx + "px"
el.style.top = e.clientY - disy + "px"}}document.onmouseup = function () {
document.onmousemove = document.onmouseup = null}}}Copy the code
Drag to adjust width and height JS principle:
Style definition:
Set a drag area that extends beyond the div element itself, exposing the drag edges and setting transparency, so its upper, lower, left, and right values should be negative
Implementation steps:
- Determine where to click (up, down, left, or four corners)
- Change mouse style based on orientation
- According to the direction combined with different algorithms, calculate up, down, left and right how to adjust coordinates and width and height
Analysis of the principle
Determine the direction
Position = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect = getBoundingClientRect For example, if e.clientX is less than Position. left, the mouse clicks to the left, if e,clientX is greater than Position. right, the mouse clicks to the right, and so on. ClientX is larger than left and clientY is smaller than top.
function getDirect(disX, disY, position) {
let direct
let horizenDirect
let verticalDirect
const { left, right, top, bottom } = position
if (disX <= left) {
horizenDirect = "left"
} else if (disX >= right) {
horizenDirect = "right"
}
if (disY <= top) {
verticalDirect = "top"
} else if (disY >= bottom) {
verticalDirect = "bottom"
}
if (verticalDirect == "top" && horizenDirect == "left") {
direct = "left-top"
} else if (verticalDirect === "top" && horizenDirect === "right") {
direct = "right-top"
} else if (verticalDirect === "bottom" && horizenDirect === "left") {
direct = "left-bottom"
} else if (verticalDirect === "bottom" && horizenDirect == "right") {
direct = "right-bottom"
} else if (verticalDirect) {
direct = verticalDirect
} else if (horizenDirect) {
direct = horizenDirect
}
return direct
}
Copy the code
Setting the Mouse Style
Implementation steps:
- Listening to the
mouseenter
The event - Change the direction of the mouse through the previous judgment
cursor
style
The code is as follows:
function updateCursor(direct) {
switch (direct) {
case "left":
el.style.cursor = "w-resize"
break
case "right":
el.style.cursor = "e-resize"
break
case "bottom":
el.style.cursor = "s-resize"
break
case "top":
el.style.cursor = "n-resize"
break
case "right-bottom":
el.style.cursor = "se-resize"
break
case "left-bottom":
el.style.cursor = "sw-resize"
break
case "right-top":
el.style.cursor = "ne-resize"
break
case "left-top":
el.style.cursor = "nw-resize"
break
default:
el.style.cursor = "auto"
}
}
el.onmouseenter = function (e) {
e.stopPropagation()
const disX = e.clientX // Get the value of cursor x when the mouse is pressed
const disY = e.clientY // Get the value of cursor Y when the mouse is pressed
const position = win.getBoundingClientRect() // Parent element coordinates
const direct = getDirect(disX, disY, position) // Get the direction
updateCursor(direct)
}
Copy the code
Dynamically calculate the horizontal and vertical coordinates and width height of each direction according to the direction
Analysis principle:
For example, if you drag from the left, first drag from left to right, then the width of div should be reduced, and the abscissa of div should be increased. At this time, the ordinate does not change, and the height does not change, so the value of the reduced width is the variable deltaX generated by the drag. Since the width should be reduced, So this deltaX is going to be negative plus the original width which is the width of the drag, and the distance you move is going to be the same deltaX, but since the x-coordinate is increasing, it’s going to be -deltax, plus the original x-coordinate which is the x-coordinate after you move it. The principle of the ordinate is similar and will not be repeated. If you drag from right to left, the width decreases and the height stays the same, but the coordinates to the left of the div do not move, so the left should not change
The code is as follows:
// Width and height limit
const limit = {
w: 200.h: 200
}
el.onmousedown = function (e) {
e.stopPropagation()
const disX = e.clientX // Get the value of cursor x when the mouse is pressed
const disY = e.clientY // Get the value of cursor Y when the mouse is pressed
const disW = win.offsetWidth // Get the width of the div before the drag
const disH = win.offsetHeight // Get the height of the div before the drag
const position = win.getBoundingClientRect() // Parent element coordinates
const direct = getDirect(disX, disY, position) // Get the direction
updateCursor(direct) // Update the mouse pointer
document.onmousemove = (d) = > {
d.stopPropagation()
let w, h
let x, y
switch (direct) {
case "left":
w = disX - d.clientX + disW
w = w < limit.w ? limit.w : w // Width limit
h = disH
x = position.left + d.clientX - disX // Move left
break
case "right":
w = d.clientX - disX + disW
w = w < limit.w ? limit.w : w // Width limit
h = disH
break
case "bottom":
w = disW
h = d.clientY - disY + disH
break
case "top":
w = disW
h = disY - d.clientY + disH
h = h < limit.h ? limit.h : h // Height limit
y = position.top + d.clientY - disY
break
case "left-top":
x = position.left + d.clientX - disX
y = position.top + d.clientY - disY
w = disX - d.clientX + disW
h = disY - d.clientY + disH
w = w < limit.w ? limit.w : w // Width limit
h = h < limit.h ? limit.h : h // Height limit
break
case "left-bottom":
x = position.left + d.clientX - disX // Move left
w = disX - d.clientX + disW
h = d.clientY - disY + disH
w = w < limit.w ? limit.w : w // Width limit
break
case "right-top":
w = d.clientX - disX + disW
h = disY - d.clientY + disH
y = position.top + d.clientY - disY
w = w < limit.w ? limit.w : w // Width limit
h = h < limit.h ? limit.h : h // Height limit
break
case "right-bottom":
w = d.clientX - disX + disW
h = d.clientY - disY + disH
w = w < limit.w ? limit.w : w // Width limit
h = h < limit.h ? limit.h : h // Height limit
break
}
win.style.width = w + "px" // The width of the dragged object
win.style.height = h + "px" // The height of the dragged object
if (x) {
win.style.left = x + "px"
}
if (y) {
win.style.top = y + "px"}}Copy the code
Conclusion:
I was realized by using the vue instructions for operating the dom, feel also more convenient to use and details are optimized space, such as performance optimization, feeling now drag sometimes caton, overall, through this project of actual combat training, for a little blurred before the event location relevant knowledge more clearly some, It also gives you a clearer understanding of drag-and-drop implementations. This is the main harvest of the actual combat.
Full code address:
Gitee.com/nabaonan/ma…
References:
Blog.csdn.net/bbsyi/artic… www.jb51.net/article/133… www.jianshu.com/p/824eb6f9d…