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 elementdeltaX
  • Mouse position minusdeltaXFind 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 themouseenterThe event
  • Change the direction of the mouse through the previous judgmentcursorstyle

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…