麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

基于Fixed定位的框選功能的實現代碼

2019-11-19 11:35:36
字體:
來源:轉載
供稿:網友

最近項目涉及到一個支持批量操作的小需求,交互上需要使用框選來觸發。在查閱了一些資料后發現,網上的方案基本都是基于絕對定位布局的,此方案如果是針對全局(在body上)的框選,還是可用的。但是現實需求里幾乎都是針對某個區域的框選。如果用絕對定位實現就比較繁瑣了,需要調整定位原點。下面介紹一種基于Fixed定位的框選實現。

需求描述

 

  • 按住鼠標左鍵不放,移動鼠標出現選擇框
  • 在鼠標移動的過程中,在框選范圍內的元素高亮
  • 松開鼠標左鍵,彈出編輯框,批量操作所有被框選的元素

實現

事件綁定

首先梳理一下需要用到的事件。

按住鼠標左鍵,因為并沒有原生的鼠標左鍵按下事件,所以使用mousedown事件配合setTimeout模擬實現。mousedown事件綁定在當前區域上。 使用一個標志變量mouseOn來代表是否開始繪制

handleMouseDown(e) { // 判斷是否為鼠標左鍵被按下 if (e.buttons !== 1 || e.which !== 1) return; this.settimeId = window.setTimeout(() => {  this.mouseOn = true;  // 設置選框的初始位置  this.startX = e.clientX;  this.startY = e.clientY; }, 300);},handleMouseUp(e) { //在mouseup的時候清除計時器,如果按住的時間不足300毫秒 //則mouseOn為false this.settimeId && window.clearTimeout(this.settimeId) if (!this.mouseOn) return;}

這里有一個小的注意點,就是clearTimeout一定要寫成 window.clearTimeout ,否則在vue里會報錯timeout.close is not a function,具體的原因尚未找到,有大佬了解望告知。

鼠標移動,使用mousemove事件。 鼠標抬起,使用mouseup事件,注意抬起事件需要 綁定在document上 。因為用戶的框選操作不會局限在當前區域,在任意位置松開鼠標都應能夠結束框選的繪制。

選框繪制

在明確了事件之后,就只需要在幾個事件中填充具體的繪制和判斷邏輯了。先來看繪制的邏輯。在mousedown事件中,設置選框的初始位置,也就是鼠標按下的位置。這里我們提前寫好一個div,用來代表選框。

<div class="promotion-range__select" ref="select"></div>.promotion-range__select { background: #598fe6; position: fixed; width: 0; height: 0; display: none; top: 0; left: 0; opacity:.6; pointer-events: none;}

按下后顯示這個div并且設置初始定位即可

this.$refs.select.style.cssText = `display:block;                  left:${this.startX}px;                  top:${this.startY}px                  width:0;                  height:0;`;

有了初始位置,在mousemove事件中,設置選框的寬高和定位。

handleMouseMove(e) { if (!this.mouseOn) return; const $select = this.$refs.select; const _w = e.clientX - this.startX; const _h = e.clientY - this.startY; //框選有可能是往左框選,此時框選矩形的左上角就變成 //鼠標移動的位置了,所以需要判斷。同理寬高要取絕對值 this.top = _h > 0 ? this.startY : e.clientY; this.left = _w > 0 ? this.startX : e.clientX; this.width = Math.abs(_w); this.height = Math.abs(_h); $select.style.left = `${this.left}px`; $select.style.top = `${this.top}px`; $select.style.width = `${this.width}px`; $select.style.height = `${this.height}px`;},

如果使用絕對定位,就要去校準坐標原點了,在布局中嵌套多個relative定位容器的情況下,就非常繁瑣了。使用fixed定位就不需要考慮相對于哪個容器的問題了。

判斷被框選的內容

//獲取目標元素const selList = document.getElementsByClassName( "promotion-range__item-inner");const { bottom, left, right, top } = $select.getBoundingClientRect();for (let i = 0; i < selList.length; i++) { const rect = selList[i].getBoundingClientRect(); const isIntersect = !(  rect.top > bottom ||  rect.bottom < top ||  rect.right < left ||  rect.left > right ); selList[i].classList[isIntersect ? "add" : "remove"]("is-editing");}

判斷使用了getBoundingClientRect,定義引用自MDN

返回值是一個 DOMRect 對象,這個對象是由該元素的 getClientRects() 方法返回的一組矩形的集合, 即:是與該元素相關的CSS 邊框集合 。

DOMRect 對象包含了一組用于描述邊框的只讀屬性――left、top、right和bottom,單位為像素。除了 width 和 height 外的屬性都是相對于 視口的左上角 位置而言的。

從定義中可以看到getBoundingClientRect中獲取的left、top、right和bottom是相對于視口左上角的,這和fixed定位的定義是一致的。因此,我們僅需要對比選框和被框選元素的四個定位值即可。

rect.top > bottom 被框選元素位于選框上方

rect.bottom < top 被框選元素位于選框下方

rect.right < left 被框選元素位于選框左側

rect.left > right 被框選元素位于選框右側

排除這四種情況以外就是選框和被框選元素存在交集,給這些div加上class,因為移動過程中也需要讓用戶感知到被框選的元素,所以上述方法在mousemove中也要執行。

在mouseup中判斷被框選元素后,將選框置為display:none。

功能demo地址

參考鏈接

http://www.companysz.com/article/161132.htm
https://developer.mozilla.org/zh-CN/docs/Web/CSS/position
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 久久久久久久久久久影视 | 久久精品国产99久久久古代 | 最新中文字幕第一页视频 | 一级看片免费视频 | 亚洲成人精品久久 | 中文字幕观看 | 黄色男女视频 | 精品国产1区2区3区 av视屏 | av国产在线被下药迷网站 | 亚洲看片网 | 高清在线国产 | hdhdhdhd19日本人| 亚洲国产网站 | 国产一级在线看 | 一级电影免费在线观看 | 黑人一区二区三区四区五区 | 国产午夜精品久久久久久免费视 | xnxx 美女19| 日韩毛片网站 | 一区二区三区无码高清视频 | 日韩深夜视频 | 91精品国产乱码久久久久久久久 | 一级黄色毛片子 | 超碰97人人艹 | 国产精品视频在线观看免费 | 国产一级αv片免费观看 | 久久久久久久久久久久久久av | 欧美日韩在线视频一区 | 国产精品免费小视频 | 久久国产经典 | 羞羞视频入口 | 粉嫩粉嫩一区二区三区在线播放 | 色诱亚洲精品久久久久久 | 全黄裸片武则天一级第4季 偿还电影免费看 | 永久免费黄色片 | 黄色免费在线网站 | 亚洲成人中文字幕在线 | 素人视频免费观看 | av电影网在线观看 | 成年片在线观看 | 中文字幕观看 |