introductionThe company's recent Vue front-end project requirements: realize the dragging of pop-up windows, four-side stretching and diagonal stretching, as well as pop-up window boundary processing. I used vue's custom instructions to write the drag.js file to share with everyone to learn together. The following code is a schematic demo I extracted for reference only. This is my first technical sharing as a front-end newbie. If there are any mistakes, please criticize and correct me! Page Layout<template> <div class="parameter" v-dialogDrag > <div class="title">Title<div class="close"> <img src="../assets/close.png" alt="" > </div> </div> <div class="content">Content area</div> </div> </template> <style lang="less"> .parameter { height: 569px; width: 960px; position: absolute; left: 50%; top: 50%; margin-left: calc(-960px / 2); margin-top: calc(-569px / 2); z-index: 999; background: #fff; box-sizing: border-box; box-shadow: 0px 12px 32px 0px rgba(0, 0, 0, 0.08); border-radius: 2px; .title { display: flex; font-size: 16px; height: 48px; line-height: 48px; background: #f5f5f5; box-sizing: border-box; box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.12); border-radius: 2px 2px 0px 0px; padding: 0 20px; z-index: 99; font-size: 16px; font-weight: 500; color: rgba(0, 0, 0, 0.85); .close { img { width: 10px; } margin-left: auto; // right alignment} } .content { display: flex; justify-content: center; align-items: center; height: calc(100% - 48px); box-sizing: border-box; background: #fff; overflow:auto; } } </style> The actual effect of the page layout is as follows: drag.js fileYou can import the drag.js file globally in main.js, or you can import it separately in the pop-up component to see if there are other usage scenarios. Project directory screenshot main.js globally imports drag.js import Vue from 'vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue' import '../drag.js' Vue.config.productionTip = false Vue.use(ElementUI); new Vue({ render: h => h(App), }).$mount('#app') Pop-up window drag implementation and boundary restrictionsimport Vue from 'vue' // v-dialogDrag: pop-up window drag + horizontal stretch + diagonal stretch Vue.directive('dialogDrag', { bind(el) { // dialogHeaderEl is the title bar, bind the mousedown event for dragging const dialogHeaderEl = el.querySelector('.title') // dragDom is the dom element bound to the instruction. Define variables to facilitate distinction const dragDom = el // Get all CSS attributes compatibility writing method ie dom element.currentStyle firefox google window.getComputedStyle(dom element, null); const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null) // Define mouse press event const moveDown = e => { // e.clientX, Y: X, Y coordinates of the mouse relative to the browser's visible window // offsetTop, offsetLeft: The distance of the current element relative to the top and left of its offsetParent element. Here, title has no positioning offset, so it is 0 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : // For compatibility with ie if (styL === 'auto') styL = '0px' let styT = sty.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 (sty.left.includes('%')) { styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100) 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.left = `${left + styL}px` dragDom.style.top = `${top + styT}px` // Stop the pop-up window from moving when the mouse is raised document.onmouseup = function () { document.onmousemove = null document.onmouseup = null } } dialogHeaderEl.onmousedown = moveDown } }) Mouse pointer hover styleThe pop-up window does not set the cursor: move hover style because it refers to the actual effect of browser dragging. If you want to set move, you need to add boundary judgment conditions. Determine the mouse hover pointer type, For more styles of mouse pointer hover, please refer to MDN // Define mouse hover style const CURSORTYPE = { top: 'n-resize', bottom: 's-resize', left: 'w-resize', right: 'e-resize', // right_top is written to facilitate data processing in the following code right_top: 'ne-resize', left_top: 'nw-resize', left_bottom: 'sw-resize', right_bottom: 'se-resize', default: 'default', }; // Determine the mouse hover pointer type const checkType = obj => { const { x, y, left, top, width, height } = obj let type if (x > left + width - 5 && el.scrollTop + y <= top + height - 5 && top + 5 <= y) { type = 'right' } else if (left + 5 > x && el.scrollTop + y <= top + height - 5 && top + 5 <= y) { type = 'left' } else if (el.scrollTop + y > top + height - 5 && x <= left + width - 5 && left + 5 <= x) { type = 'bottom' } else if (top + 5 > y && x <= left + width - 5 && left + 5 <= x) { type = 'top' } else if (x > left + width - 5 && el.scrollTop + y > top + height - 5) { type = 'right_bottom' } else if (left + 5 > x && el.scrollTop + y > top + height - 5) { type = 'left_bottom' } else if (top + 5 > y && x > left + width - 5) { type = 'right_top' } else if (top + 5 > y && left + 5 > x) { type = 'left_top' } return type || 'default' } Four-side stretching and diagonal stretchingThere was a slight deviation in my thinking during the diagonal stretching process. I found that the browser window can be stretched diagonally in the X-axis direction, the Y-axis direction, and the bevel edge, so I divided it into three situations for judgment. However, the actual pop-up window effect can only be stretched a little bit, which does not meet the stretching requirements. After thinking about it, I found that the actual diagonal stretching is the superposition of the X and Y axes and the reference vector. Because diagonal stretching is the superposition of the X-axis and the Y-axis, we consider encapsulating the four-side stretching function and directly calling the corresponding X and Y axes for diagonal stretching to reduce the amount of code. When passing data, the data needs to be packaged because diagonal stretching requires two values to be passed, while four-sided stretching only requires one value. For example: the right side passes the data // Determine boundary conditions const boundaryLimit = obj => { const { left, top, width, height, diffX, diffY, screenHeight, screenWidth, arr } = obj if (arr[0] == 'right' || arr[1] == 'right') { if (width + diffX > screenWidth - left) { dragDom.style.width = screenWidth - left + 'px' } else { dragDom.style.width = width + diffX + 'px' } } if (arr[0] == 'left' || arr[1] == 'left') { if (width - diffX > width + left) { dragDom.style.width = width + left + 'px' dragDom.style.left = - parseInt(sty.marginLeft) + 'px' } else { dragDom.style.width = width - diffX + 'px' // left actually = left + marginLeft. When calculating, marginLeft needs to be subtracted. dragDom.style.left = left + diffX - parseInt(sty.marginLeft) + 'px' } } if (arr[0] == 'top' || arr[1] == 'top') { if (height - diffY > height + top) { dragDom.style.height = height + top + 'px' dragDom.style.top = - parseInt(sty.marginTop) + 'px' } else { dragDom.style.height = height - diffY + 'px' // top actually = top + marginTop. MarginTop needs to be subtracted when calculating. dragDom.style.top = top + diffY - parseInt(sty.marginTop) + 'px' } } if (arr[0] == 'bottom' || arr[1] == 'bottom') { if (height + diffY > screenHeight - top) { dragDom.style.height = screenHeight - top } else { dragDom.style.height = height + diffY + 'px' } } } dragDom.onmousedown = e => { const x = e.clientX const y = e.clientY const width = dragDom.clientWidth const height = dragDom.clientHeight const left = dragDom.offsetLeft const top = dragDom.offsetTop const screenWidth = document.documentElement.clientWidth || document.body.clientWidth const screenHeight = document.documentElement.clientHeight || document.body.clientHeight // dragDom.style.userSelect = 'none' let type = checkType({ x, y, left, top, width, height }) // Determine if it is a pop-up window header if (x > left && x < left + width && y > top + 5 && y < top + dialogHeaderEl.clientHeight) { // dialogHeaderEl.onmousedown = moveDown } else { document.onmousemove = function (e) { // Disable default events when moving e.preventDefault() let endX = e.clientX let endY = e.clientY let diffX = endX - x let diffY = endY - y let arr // Convert type to array format to simplify code judgment and call if (type.indexOf('_') == -1) { arr = [type, ''] } else { arr = type.split('_') } boundaryLimit({ left, top, width, height, diffX, diffY, screenHeight, screenWidth, arr }) } // Stretch ends document.onmouseup = function () { document.onmousemove = null document.onmouseup = null } } } Stretch Interference Because the pop-up window is set <template> <div class="parameter" v-dialogDrag > <div class="title">Title<div class="close"> <img src="../assets/close.png" alt="" > </div> </div> <div class="content">Content area</div> <div class="rightBlank">123</div> <div class="bottomBlank">456</div> </div> </template> The page effect after the change is Attached project warehouse address This is the end of this article about Vue custom instructions to implement pop-up window dragging, four-side stretching and diagonal stretching. For more related vue custom instruction pop-up window dragging 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:
|
<<: Detailed installation instructions for the cloud server pagoda panel
>>: Detailed explanation of MySQL sql99 syntax inner join and non-equivalent join
Table of contents Preface 1. Set the prototype on...
Forgetting the password is a headache. What shoul...
Table of contents Vue custom directive Custom dir...
Table of contents 1. Background running jobs 2. U...
Preface To delete a table, the command that comes...
To remove the underline of a hyperlink, you need t...
Background: During the development process, we of...
Library Operations Query 1.SHOW DATABASE; ----Que...
Table of contents 1. Schematic diagram of group q...
background Since I converted all my tasks to Dock...
The vertically adjacent edges of two or more bloc...
1. Download the zip archive version from the offi...
Table of contents Port-related concepts: Relation...
1. Installation Install using yum ##Automatically...
I didn't intend to write this blog, but durin...