Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to customize the Vue instruction v-selectable similar to jQueryUISelectable

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

In this issue, the editor will bring you about how to customize the Vue instruction v-selectable similar to jQueryUISelectable. The article is rich in content and analyzes and describes it from a professional point of view. I hope you can get something after reading this article.

If you don't say much, let's see the effect first.

In fact, it is a function that can press and hold the mouse to select items in an area. I believe those who have used Jquery UI all know that this is the function of selectable, but if we develop with Vue, there is no similar plug-in, of course, you can still take jquery directly, but I don't want to introduce jquery and jquery UI in my project, so I try to achieve similar functions by myself.

There are two steps to achieve this function. The first step is to implement the function of the mouse selection area, and the first step is to add an active class to the selected item in this area.

First look at how to hold down the mouse to draw a dotted frame, the idea is to first change the positioning of the container element to relative, and then judge that when the mouse is pressed (mousedown), remember the location of the click point (e.layerX, e.layerY), and then monitor the position of the mouse in real time (e.layerX, e.layerY) when the mouse is moved (mousemove) With these two locations, you can dynamically create a div, position it as absolute, then add it to the container box, and clear it one box at a time. Why use e.layerX e.layerY?

LayerX layerY

If the position style of an element is not the default static, we say that the element has a positioning attribute.

The nearest element with positioning attribute is found in the element that currently triggers the mouse event and its ancestor element, and the offset value of the mouse is calculated to find the diplomatic point in the upper-left corner of the element's border as the relative point. If no element with positioning attributes is found, the offset is calculated relative to the current page, which is now equivalent to pageY. Follow this idea to complete the following code:

Export default (Vue, options = {}) = > {const listener = (ele, binding) = > {let reactArea = {startX: 0, startY: 0, endX: 0, endY: 0} / / whether to keep pressing the mouse let isMouseDown = false let areaSelect = {} / / change the element positioning to relative ele.style.position = 'relative' ele.addEventListener (' mousedown', function (e) {reactArea.startX = e.layerX) ReactArea.startY = e.layerY IsMouseDown = true}) ele.addEventListener ('mousemove' Function (e) {if (isMouseDown) {let preArea = ele.getElementsByClassName ('v e.layerX reactArea.endY selected preArea') if (preArea.length) {ele.removeChild (preArea [0])} reactArea.endX = e.layerX reactArea.endY = e.layerY let leftValue = 0 let topValue = 0 let widthValue = Math.abs (reactArea.startX-reactArea.endX) Let heightValue = Math.abs (reactArea.startY-reactArea.endY) if (reactArea.startX > = reactArea.endX) {leftValue = reactArea.endX} else {leftValue = reactArea.startX} if (reactArea.startY > reactArea.endY) {topValue = reactArea.endY} else {topValue = reactArea.startY} / / at the same time Width and height just began to draw a dotted frame if (reactArea.startX! = reactArea.endX & & reactArea.startY! = reactArea.endY) {areaSelect = document.createElement ('div') areaSelect.classList.add ("v-selected-area") areaSelect.style.position = "absolute" AreaSelect.style.left = leftValue + 'px' areaSelect.style.top = topValue +' px' areaSelect.style.width = widthValue + 'px' areaSelect.style.height = heightValue +' px' areaSelect.style.border = "1px dashed grey" ele.append (areaSelect)}}) ele.addEventListener ('mouseup' Function (e) {isMouseDown = false / / areaSelect if (areaSelect & & areaSelect.childNodes & & ele.contains (areaSelect)) {ele.removeChild (areaSelect)} areaSelect = null})} Vue.directive ('selectable', {inserted:listener, updated:listener})}

At this time, the effect of drawing dotted lines can be achieved.

The next step is how to make each item selected. The idea is to iterate through all the child elements of the container ul, li, and then determine whether each li is inside the selected box. Then look at the offsetLeft and offsetTop of each element to calculate the position of the element relative to the parent element, and then determine the width and height of the child element through getBoundingClientRect (). Height and getBoundingClientRect (). Width. These can calculate the location and size of the element, and then how to determine whether the element is in the selection area? My rule is that any of the four corners of the element is in the selection area or inside the selection area, even if the element is selected (this judgment doesn't feel perfect). Follow this line of thinking and continue to complete our code:

Export default (Vue, options = {}) = > {const listener = (ele, binding) = > {let reactArea = {startX: 0, startY: 0, endX: 0, endY: 0} / / whether to keep pressing the mouse let isMouseDown = false let areaSelect = {} / / change the element positioning to relative ele.style.position = 'relative' ele.addEventListener (' mousedown', function (e) {reactArea.startX = e.layerX; reactArea.startY = e.layerY) IsMouseDown = true}) ele.addEventListener ('mousemove' Function (e) {if (isMouseDown) {let preArea = ele.getElementsByClassName ('v Merry selectedMuarea') if (preArea.length) {ele.removeChild (preArea [0])} reactArea.endX = e.layerX reactArea.endY = e.layerY let leftValue = 0 let topValue = 0 let widthValue = Math.abs (reactArea.startX-reactArea.endX) let heightValue = Math.abs (reactArea.startY-reactArea.endY) if (reactArea.startX > = reactArea.endX) {leftValue = reactArea.endX } else {leftValue = reactArea.startX} if (reactArea.startY > reactArea.endY) {topValue = reactArea.endY} else {topValue = reactArea.startY} / / decide to have width and height at the same time before drawing dotted frame if (reactArea.startX! = reactArea.endX & & reactArea.startY! = reactArea.endY) {areaSelect = document.createElement ('div') areaSelect.classList.add ("v-selected-area") areaSelect.style.position = "absolute" AreaSelect.style.left = leftValue + 'px' areaSelect.style.top = topValue +' px' areaSelect.style.width = widthValue + 'px' areaSelect.style.height = heightValue +' px' areaSelect.style.border = "1px dashed grey" ele.append (areaSelect)} let children = ele.getElementsByTagName ('li') for (let I = 0; I

< children.length ; i ++ ){ let childrenHeight = children[i].getBoundingClientRect().height let childrenWidth = children[i].getBoundingClientRect().width //每个li元素的位置 let offsetLeft = children[i].offsetLeft let offsetTop = children[i].offsetTop //每个li元素的宽高 let endPositionH = childrenHeight + offsetTop let endPositionW = childrenWidth + offsetLeft //五个条件满足一个就可以判断被选择 //一是右下角在选择区域内 let require1 = endPositionH >

TopValue & & endPositionW > leftValue & & endPositionH

< topValue + heightValue && endPositionW < leftValue + widthValue //二是左上角在选择区域内 let require2 = offsetTop >

TopValue & & offsetLeft > leftValue & & offsetTop

< topValue + heightValue && offsetLeft < leftValue + widthValue //三是右上角在选择区域内 let require3 = offsetTop >

TopValue & & offsetLeft + childrenWidth > leftValue & & offsetTop

< topValue + heightValue && offsetLeft + childrenWidth< leftValue + widthValue //四是左下角在选择区域内 let require4 = offsetTop + childrenHeight >

TopValue & & offsetLeft > leftValue & & offsetTop + childrenHeight

< topValue + heightValue && offsetLeft < leftValue + widthValue //五选择区域在元素体内 let require5 = offsetTop < topValue && offsetLeft < leftValue && offsetTop + childrenHeight >

TopValue + heightValue & & offsetLeft + childrenWidth > leftValue + widthValue if (require1 | | require2 | | require3 | | require4 | | require5) {children.classList.add ('active')} else {children [I] .classList.remove (' active')}) ele.addEventListener ('mouseup', function (e) {isMouseDown = false if (areaSelect & areaSelect.childNodes & ele.contains) {ele.removeChild (areaSelect)} areaSelect = null})} Vue.directive (' selectable') {inserted:listener, updated:listener})}

When you're done, you'll see how to use the html structure:

Item1 item2 item3 item4 item5 item6

Note that the v-selectable of ul is our custom instruction, but it must be Vue.use before using it.

Import Vue from 'vue'import Selectable from' @ / components/vue-selectable/vue-selectable.js' / / this is changed to your js path Vue.use (Selectable)

Add a little more style to our ul li, and notice that our selected item will be added an active class, which will change the style of the selected item.

Ul {margin: 40px 40px 40px 40px; border: 1px solid red; width: 300px; padding-bottom: 20px;} ul li {width: 200px; height: 30px; list-style: none; border: 1px solid black; margin-left: 10px; margin-top: 30px; text-align: center; line-height: 30px; user-select:none;} ul li.active {background-color: red;}

In this way, the initial effect can be achieved. In fact, there are still many small bug in the process of running the code, this article just provides a simple idea and code, more functions can be modified to add their own code. If you don't understand why this custom instruction is written in this way, you can refer to my other article to customize the lazy loading image plug-in v-lazyload.

The above is the editor for you to share how to customize the Vue instruction v-selectable similar to jQueryUISelectable, if you happen to have similar doubts, please refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report