Practice of Vue global custom instruction Modal drag

Practice of Vue global custom instruction Modal drag

background

The project I have been working on recently is a project built with Vue2, and the UI framework uses antdV. A lot of Modal dialog boxes are used in the project. Then suddenly one day the product said, "Why can't this dialog box be moved? It blocks my view of the information." There is no way, if there is a demand, we have to do it. This is the new generation of workers.

First, I went to the antdV official website to look at the configuration properties and methods of Modal to see if there are any properties or methods that can solve this problem directly, but I didn't find any. The second step was to start asking Baidu. There were some related blogs, but generally speaking, they were too diverse and difficult to understand. Then I found that there was an interesting way to use global custom specifications, and then I started to solve the problem myself.

Implementation ideas

First of all, we mainly want to complete the effect of moving the dialog box after pressing the left button when the mouse is placed on the head part of the Modal box.

Here we need to get the header element and listen to its onmousedown method, then during the onmousedown method, we calculate the height and width of the dialog box to set boundary limits to prevent it from moving off the screen, then listen to the document.onmousemove method to calculate the direction and distance of the mouse movement, and then adjust the position of the dialog box based on this.

Code Implementation

import Vue from 'vue'

// Pop-up window drag properties/**
 * @directive custom attributes * @todo pop-up drag attributes * @desc add v-drag using any html loaded inside the pop-up
 * @param .ant-modal-header The properties of the pop-up window header used for dragging* @param .ant-modal The properties to drag*/
Vue.directive('drag', (el, binding, vnode, oldVnode) => {
  // inserted (el, binding, vnode, oldVnode) {
  Vue.nextTick(() => {
    const isThemeModal = el.classList.contains('grid-theme')
    const dialogHeaderEl = isThemeModal ? el.querySelector('.ant-tabs-bar') : document.querySelector('.ant-modal-header')
    const dragDom = isThemeModal ? el.querySelector('.ant-modal') : document.querySelector('.ant-modal')
    //dialogHeaderEl.style.cursor = 'move';
    dialogHeaderEl.style.cssText += ';cursor:move;'
    // dragDom.style.cssText += ';top:0px;'

    // Get the original attributes ie dom element.currentStyle firefox google window.getComputedStyle(dom element, null);
    const sty = (function () {
      if (window.document.currentStyle) {
        return (dom, attr) => dom.currentStyle[attr]
      } else {
        return (dom, attr) => getComputedStyle(dom, false)[attr]
      }
    })()

    dialogHeaderEl.onmousedown = (e) => {
      // Mouse pressed, calculate the distance between the current element and the visible area const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop

      const screenWidth = document.body.clientWidth // Current width of body const screenHeight = document.documentElement.clientHeight // Visible area height (should be body height, but cannot be obtained in some environments)

      const dragDomWidth = dragDom.offsetWidth // Dialog box width const dragDomheight = dragDom.offsetHeight // Dialog box height const minDragDomLeft = dragDom.offsetLeft
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth - (isThemeModal ? 10 : 0)

      const minDragDomTop = dragDom.offsetTop
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight - (isThemeModal ? 10 : 0)

      // Get the value with px regular expression to replace let styL = sty(dragDom, 'left')
      let styT = sty(dragDom, 'top')

      // Note that in IE, the first value obtained is the component's own 50% and the value is assigned to px after moving
      if (styL.includes('%')) {
        // eslint-disable-next-line no-useless-escape
        styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
        // eslint-disable-next-line no-useless-escape
        styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
      } else {
        styL = +styL.replace(/\px/g, '')
        styT = +styT.replace(/\px/g, '')
      };

      document.onmousemove = function (e) {
        // Calculate the moving distance through event delegation let left = e.clientX - disX
        let top = e.clientY - disY

        // Boundary processing if (-(left) > minDragDomLeft) {
          left = -(minDragDomLeft)
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft
        }

        if (-(top) > minDragDomTop) {
          top = -(minDragDomTop)
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop
        }
        // Move the current element dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
      }

      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
    }
  })
})

Component call
A-modal component can be set to v-drag

...
<a-modal v-model="visible" title="Prompt" :maskClosable="false" @cancel="handleCancle" @ok="handleOk" v-drag>
  <p>Are you sure you want to delete the field?</p>
</a-modal>
...

Achieve results

This is the end of this article about the practice of Vue global custom directive Modal drag. For more relevant Vue Modal drag content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue custom directive details
  • A detailed guide to custom directives in Vue
  • Understand the usage of Vue2.x and Vue3.x custom instructions and the principle of hook functions
  • Basic usage of custom directives in Vue
  • Detailed explanation of Vue.js directive custom instructions
  • Vue custom instructions to achieve pop-up window drag four-side stretching and diagonal stretching effect
  • Detailed explanation of Vue custom instructions

<<:  Use of nginx custom variables and built-in predefined variables

>>:  Summary of common MySQL function examples [aggregate functions, strings, numbers, time and date processing, etc.]

Recommend

Detailed explanation of node.js installation and HbuilderX configuration

npm installation tutorial: 1. Download the Node.j...

How to install redis5.0.3 in docker

1. Pull the official 5.0.3 image [root@localhost ...

Multiple ways to insert SVG into HTML pages

SVG (Scalable Vector Graphics) is an image format...

A summary of detailed insights on how to import CSS

The development history of CSS will not be introd...

Example code for implementing complex table headers in html table

Use HTML to create complex tables. Complex tables...

Mini Program to Implement Calculator Function

This article example shares the specific code of ...

React Router V6 Updates

Table of contents ReactRouterV6 Changes 1. <Sw...

A brief discussion on VUE uni-app conditional coding and page layout

Table of contents Conditional compilation Page La...

Linux Cron scheduled execution of PHP code with parameters

1. Still use PHP script to execute. Command line ...

Detailed explanation of the TARGET attribute of the HTML hyperlink tag A

The hyperlink <a> tag represents a link poin...