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

MySQL 5.6.37 (zip) download installation configuration graphic tutorial

This article shares the download, installation an...

Detailed explanation of eight methods to achieve CSS page bottom fixed

When we are writing a page, we often encounter a ...

Detailed explanation of zabbix executing scripts or instructions on remote hosts

Scenario Requirements 1. We can use the script fu...

Use of Linux bzip2 command

1. Command Introduction bzip2 is used to compress...

Do you know how to use Vue to take screenshots of web pages?

Table of contents 1. Install html2Canvas 2. Intro...

Summary of common Mysql DDL operations

Library Management Create a library create databa...

Solution to the Chinese garbled characters problem in MySQL under Ubuntu

Find the problem I have been learning Django rece...

Solution to the problem of repeated pop-up of Element's Message pop-up window

Table of contents 1. Use 2. Solve the problem of ...

MySQL 4G memory server configuration optimization

As the number of visits to the company's webs...

Realizing the effect of carousel based on jQuery

This article shares the specific code of jQuery t...

MySQL 5.7.18 download and installation process detailed instructions

MySql Download 1. Open the official website and f...

Ubuntu 16.04 kernel upgrade steps

1. Environment Ubuntu 16.04 running on a virtual ...

js development plug-in to achieve tab effect

This article example shares the specific code of ...

Do you know the difference between empty value and null value in mysql

Preface Recently I found that my friend's met...