<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        自定義類似于jQuery UI Selectable 的Vue指令v-selectable

        來源:懂視網 責編:小采 時間:2020-11-27 22:31:48
        文檔

        自定義類似于jQuery UI Selectable 的Vue指令v-selectable

        自定義類似于jQuery UI Selectable 的Vue指令v-selectable:話不多說,先看效果。 其實就是一個可以按住鼠標進行一個區域內條目選擇的功能,相信用過Jquery UI 的都知道這是selectable的功能,然而我們如果用Vue開發的話沒有類似的插件,當然你仍然可以把jquery的拿過來直接用,但是我又不想引入jquery 和 j
        推薦度:
        導讀自定義類似于jQuery UI Selectable 的Vue指令v-selectable:話不多說,先看效果。 其實就是一個可以按住鼠標進行一個區域內條目選擇的功能,相信用過Jquery UI 的都知道這是selectable的功能,然而我們如果用Vue開發的話沒有類似的插件,當然你仍然可以把jquery的拿過來直接用,但是我又不想引入jquery 和 j

        話不多說,先看效果。

          其實就是一個可以按住鼠標進行一個區域內條目選擇的功能,相信用過Jquery UI 的都知道這是selectable的功能,然而我們如果用Vue開發的話沒有類似的插件,當然你仍然可以把jquery的拿過來直接用,但是我又不想引入jquery 和 jquery UI在我的項目中,于是我就自己嘗試著實現類似的功能。

          要實現這個功能分兩步。第一步是實現鼠標選擇區域的功能,第步部是把這個區域內被選擇的item添加一個active的類。

          先看如何實現按住鼠標畫虛線框,思路是先把容器元素的定位改為relative 然后判斷當鼠標按下(mousedown)的時候,進行記住這個點擊點的位置(e.layerX , e.layerY),然后鼠標移動(mousemove)的時候,實時的監測鼠標的位置(e.layerX , e.layerY),有了這兩個位置就可以動態的創建一個div,它的定位為absolute,然后把它添加的容器框里,并且每次清空前一個框就可以了。為什么是用e.layerX e.layerY呢,

        layerX layerY

                 如果元素的position樣式不是默認的static,我們說這個元素具有定位屬性。

                 在當前觸發鼠標事件的元素和它的祖先元素中找到最近的具有定位屬性的元素,計算鼠標與其的偏移值,以找到元素的border的左上角的外交點作為相對點。如果找不到具有定位屬性的元素,那么就相對于當前頁面計算偏移,此時等同于pageY。按照這個思路完成以下代碼:

        export default (Vue, options = {}) =>{
         const listener = (ele, binding) =>{
         let reactArea = {
         startX: 0,
         startY: 0,
         endX: 0,
         endY: 0
         }
         //是否一直按下鼠標
         let isMouseDown = false
         let areaSelect = {}
         //將元素定位改為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-selected-area')
         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
         }
         //判斷同時有寬高才開始畫虛線框
         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
         })
        }

          這個時就可以實現畫虛線框的效果

          下一步是如何把每個item置為選中狀態。思路是遍歷這個容器ul 的所有子元素li ,然后判斷每個li是否在選中的框內部。然后看每個元素的offsetLeft 和 offsetTop 計算元素相對于父元素的位置,然后通過getBoundingClientRect().height 和 getBoundingClientRect().width 確定子元素的寬高。這些就可以計算出元素的位置和大小了,然后如何判斷這個元素是否在選擇區域內呢?我的規則是這個元素的四個角位置有任何一個在選擇區域內或者選擇區域就在這個區域的內部,就算是這個元素被選中了(這個判斷方式感覺不是很完美)。按照這個思路,繼續完成我們的代碼:

        export default (Vue, options = {}) =>{
         const listener = (ele, binding) =>{
         let reactArea = {
         startX: 0,
         startY: 0,
         endX: 0,
         endY: 0
         }
         //是否一直按下鼠標
         let isMouseDown = false
         let areaSelect = {}
         //將元素定位改為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-selected-area')
         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
         }
         //判斷同時有寬高才開始畫虛線框
         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[i].classList.add('active')
         }else{
         children[i].classList.remove('active')
         }
         }
         }
         })
         ele.addEventListener('mouseup', function(e) {
         isMouseDown = false
         if(areaSelect && areaSelect.childNodes && ele.contains(areaSelect)){
         ele.removeChild(areaSelect)
         }
         areaSelect = null
         })
         }
         Vue.directive('selectable',{
         inserted:listener,
         updated:listener
         })
        }

        完成之后再看看如何使用,html 結構:

        <ul v-selectable >
          <li class="square">
         item1
          </li>
          <li class="oval">
         item2
          </li>
          <li class="triangle">
         item3
          </li>
          <li class="triangle-topleft">
         item4
          </li>
          <li class="curvedarrow">
         item5
          </li>
          <li class="triangle-topleft">
         item6
          </li>
        </ul>

          注意ul的這個v-selectable就是我們自定義的指令,但是使用之前必須 Vue.use

        import Vue from 'vue'
        import Selectable from '@/components/vue-selectable/vue-selectable.js' //這個修改為你的js路徑
        Vue.use(Selectable); 

          再給我們的ul li 加點樣式,注意我們的被選擇項會被添加一個active的class,通過這個來改變選中項樣式

        <style scoped>
         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;
         }
        </style>

          這樣就可以達到開頭的效果了。實際上代碼運行過程中還是有許多小bug的,本文只是提供了一個簡單的思路和代碼,更多功能可以自己修改代碼進行添加。如果不明白這個自定義指令為什么是這樣的寫法,可以參考我的另一篇文章自定義懶加載圖片插件v-lazyload。

        //www.gxlcms.com/article/112355.htm

        總結

        以上所述是小編給大家介紹的自定義類似于jQuery UI Selectable 的Vue指令v-selectable,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        自定義類似于jQuery UI Selectable 的Vue指令v-selectable

        自定義類似于jQuery UI Selectable 的Vue指令v-selectable:話不多說,先看效果。 其實就是一個可以按住鼠標進行一個區域內條目選擇的功能,相信用過Jquery UI 的都知道這是selectable的功能,然而我們如果用Vue開發的話沒有類似的插件,當然你仍然可以把jquery的拿過來直接用,但是我又不想引入jquery 和 j
        推薦度:
        標簽: VUE ui select
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 极品色天使在线婷婷天堂亚洲| 亚洲国产精品嫩草影院在线观看 | 亚洲午夜电影在线观看| 国产精品99精品久久免费| 久久精品亚洲中文字幕无码网站 | 成人亚洲国产精品久久| 日本一道综合久久aⅴ免费| 亚洲av无码专区青青草原| 国产精品免费视频播放器| 粉色视频免费入口| 在线观看亚洲精品福利片| 久久九九全国免费| 久久精品国产亚洲AV嫖农村妇女 | 99久在线国内在线播放免费观看| 四虎影院免费视频| 亚洲丁香婷婷综合久久| 免费国产a国产片高清| 亚洲精品456在线播放| 亚欧在线精品免费观看一区| 成人亚洲国产va天堂| 又爽又黄无遮挡高清免费视频| 美女黄频a美女大全免费皮| 在线观看亚洲天天一三视| a级毛片毛片免费观看久潮喷| 亚洲AV日韩精品久久久久久久 | 99久久精品免费精品国产| 久久久久se色偷偷亚洲精品av| 拔擦拔擦8x华人免费久久| 美女无遮挡拍拍拍免费视频| 久久亚洲AV成人无码软件| jizz日本免费| 亚洲精品在线网站| 国产嫩草影院精品免费网址| 丁香花在线视频观看免费| 激情五月亚洲色图| 亚洲色偷拍区另类无码专区| 日本黄网站动漫视频免费| 免费激情网站国产高清第一页| 亚洲另类激情综合偷自拍 | 亚洲真人日本在线| 精品国产无限资源免费观看|