日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

css元素可拖动,使用css-transform实现更好的拖拽功能

發布時間:2024/9/30 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 css元素可拖动,使用css-transform实现更好的拖拽功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

拖拽功能是目前網頁上一種非常常見的功能,例如“登錄彈窗”的拖拽。本文將使用transform來實現這一功能。

一、拖拽的用戶行為分析與原理解析

二、代碼實現

三、總結

本文所涉及的案例可能會用到的一些必備的知識點:

1、JavaScript中的DOM2級事件綁定

2、正則的編寫與匹配

3、獲取元素計算后的樣式的相關API

4、鼠標坐標的位置獲取

5、ES6的模板字符串語法

6、另外,為了能夠順利使用到transform,讀者可能還需要對CSS3的一些樣式規則有些了解

因此,如果讀者對以上這些知識點的了解還有欠缺,可以在在此之前捎帶預習一下。

另外,本文配套的這個案例雖然采用的webpack構建運行,但核心代碼與之無關。

如果讀者不熟悉webpack的構建方式,也不用擔心會看不懂代碼。

文章內容難度:☆復制代碼

一、拖拽的用戶行為分析與原理解析如果讀者熟悉了這個過程并也熟知了其中的原理,可以忽略此部分

拖拽的整個過程大致可以使用此圖來描述:

元素的上邊距離頁面頂部的距離值(以下簡稱“上邊距離”)從Y(a)變成了Y(b),“左邊距離”從X(a)變成了X(b),也即完成了元素的移動。

在整個的變化過程中,有這樣的一個隱藏信息:鼠標相對于元素的坐標(distX, distY)在整個移動過程中是沒有發生變化的,用圖上的關系即可以表示為:cX(b) - X(b) = cX(a) - X(a) = distX,cY(b) - Y(b) = cY(a) - Y(a) = distY。那么,在整個移動過程中,元素的“上邊距離”= 鼠標移動中任意時刻的Y坐標 - distY,“左邊距離”= 鼠標移動中任意時刻的X坐標 - distX。那么怎么求出distX和distY呢?

我們在按下鼠標的那一刻,瀏覽器就會告訴我們鼠標的坐標(cX, cY),同時,我們也可以求出目標元素的“上邊距離”(Y)和“左邊距離”(X),這樣distX = cX - X,distY = cY - Y。

二、代碼實現

1.初始化工作

按照第一部分的分析,我們需要在按下鼠標的那一刻獲取元素的“上邊距離”和“左邊距離”。在傳統的采用【position: absolute】定位的實現方式中,這一步我們可以通過DOM的【offsetTop】和【offsetLeft】來分別獲取它們的值。但既然我們采用transform的方式來實現,就不再使用這兩個屬性了。

我們首先設置元素的一些關鍵樣式(部分UI樣式已忽略):

.drag-box-translate3d{

transform: translate3d(0, 0, 1px);

-moz-transform: translate3d(0, 0, 1px);

-webkit-transform: translate3d(0, 0, 1px);

will-change: transform;

-moz-will-change: transform;

-webkit-will-change: transform;

}復制代碼值得注意的是,我們采用translate3d的屬性值并設置了z軸的值為1px,這樣做的目的是強制瀏覽器使用GPU加速,從而獲得更加流暢的體驗。

判斷瀏覽器是否啟用GPU加速,可以在定位到該元素之后,查看元素的計算后的樣式:transform的值是matrix還是matrix3d,顯示為后者時,即表示已開啟GPU加速。

如果我們使用【position: absolute】來實現,那么初始位置的X(a)和Y(a)分別以left和top的值來分別指定,但采用transform來實現時,我們就可以使用translateX和translateY來分別指定X(a)和Y(a)。在上面的CSS設置中,X(a)和Y(a)就被分別設置為0和0。

我們需要在代碼中獲取該元素的transform的計算后的值,代碼如下:

export function getStyle(el,

attr){

if( typeof window.getComputedStyle !== 'undefined' ){

return window.getComputedStyle(el, null)[attr]

}else if(typeof el.currentStyle !== 'undefiend' ){

return el.currentStyle[attr]

}

return ''

}復制代碼

2.綁定mousedown事件并獲取distX和distY

我們準備一個獨立的文件drag.matrix.js來編寫我們的代碼,用來實現模塊化的編程。

我們首先定義一個模塊內的全局變量用來承載需要綁定拖拽功能的元素。/* 定義元素變量 */

let ELEMENT = null復制代碼

再定義一個模塊內的全局對象用來存儲計算用到的各個距離與尺寸數據。/* 定義距離尺寸的存儲池 */

let E_SIZER = {}

復制代碼

mousedown事件的回調函數如下:/**

* mousedown事件

* @param {MouseEvent} evte 鼠標事件對象

* @returns {undefined}

**/

function bindMouseDownEvent(evte){

// 阻止冒泡

evte.stopPropagation()

// 阻止默認事件

evte.preventDefault()

// 解析matrix的正則

let matrix3dReg = /^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/,

matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/

// 獲取解析后的transform樣式屬性值(計算后的樣式)

let matrix3dSourceValue = util.getStyle(

evte.target,

'transform'

)

// 使用正則解析matrix

let matrix3dArrValue =

matrix3dSourceValue.match( matrix3dReg ) || matrix3dSourceValue.match( matrixReg )

// 記錄鼠標點擊時的坐標

E_SIZER['clientX'] = evte.clientX

E_SIZER['clientY'] = evte.clientY

// 記錄matrix解析后的translateX & translateY的值

E_SIZER['targetX'] = matrix3dArrValue[1]

E_SIZER['targetY'] = matrix3dArrValue[2]

// 計算坐標邊界巨鹿

E_SIZER['distX'] = E_SIZER['clientX'] - E_SIZER['targetX']

E_SIZER['distY'] = E_SIZER['clientY'] - E_SIZER['targetY']

// 綁定mousemove事件

document.addEventListener('mousemove', bindMouseMoveEvent, false)

} 復制代碼

被設置了transform屬性值為translate3d的元素,瀏覽器會將這個樣式的屬性值計算為matrix3d(...)的矩陣。

那么怎么獲取到translateX和translateY的值呢?

這里提供兩個正則,用來解析matrix或matrix3d的值并得到translateX和translateY的值:

/^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/

/^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/復制代碼

這兩個正則可以直接使用,例如:

有了以上的分析和知識儲備,我們就可以在鼠標按下的那一刻,獲取到元素的初始X(a)和Y(a)的值了,也即上述的【bindMouseDownEvent】函數。

3.綁定mousemove事件移動元素

mouseover事件的回調函數如下:/**

* mousemove事件

* @param {MouseEvent} evte 鼠標事件對象

* @returns {undefined}

**/

function bindMouseMoveEvent(evte){

evte.stopPropagation()

evte.preventDefault()

let moveX = evte.clientX - E_SIZER['distX']

let moveY = evte.clientY - E_SIZER['distY']

// 寫入style

ELEMENT.style.transform =

ELEMENT.style.mozTransform =

ELEMENT.style.webkitTransform =

`translate3d(${moveX}px, ${moveY}px, 1px)`

} 復制代碼

如果讀者對本文第一部分的分析理解了的話,對于這一段函數應該會比較容易理解了。我們只要將鼠標在移動中的坐標值“轉換”到元素的身上,即可完成對元素的實時移動了。

我們需要將【bindMouseMoveEvent】綁定到document上,因為在快速移動過程中,鼠標實際上會移出元素,如果直接將該回調函數綁定到元素上,可能會導致移動過程異常終止。

4.綁定mouseup解除功能

mouseup事件的回調函數如下:/**

* mouseup事件

* @param {MouseEvent} evte 鼠標事件對象

* @returns {undefined}

**/

function bindMouseUpEvent(evte){

evte.stopPropagation()

evte.preventDefault()

document.removeEventListener('mousemove', bindMouseMoveEvent)

} 復制代碼

我們需要將綁定到document上的mousemove回調事件函數移除。

5.初始化事件綁定/**

* 綁定事件

* @param {MouseEvent} evte 鼠標事件對象

* @returns {undefined}

**/

function initBindEvent(){

// 綁定mousedown事件

ELEMENT.addEventListener('mousedown', bindMouseDownEvent, false)

// 綁定mouseup事件

document.addEventListener('mouseup', bindMouseUpEvent, false)

}復制代碼

同樣的,我們需要將mouseup事件的回調函數綁定到document。

這樣,我們我完成了拖拽功能的主體部分的開發工作,只要將其功能綁定到指定的元素上即可(可以訪問文章尾部的github地址來體驗)。‘

三、總結

今天我們使用transform對傳統的使用position: absolute的拖拽功能進行了升級,避免了在頁面元素在移動過程中的不斷的回流重繪,從而提升了功能性能。

在不考慮對老舊瀏覽器的兼容的情況下,可以盡量地使用CSS來獲取更優的用戶體驗。

期待點贊;不足之處,歡迎指出。

2019-09-20

知乎專欄:前端小知識

總結

以上是生活随笔為你收集整理的css元素可拖动,使用css-transform实现更好的拖拽功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产剧情在线观看 | 国产日韩一区二区三区 | 欧美色狠| 成人h视频在线 | www.四虎.com| 干干天天 | 12av毛片| 热久久亚洲 | 国产中文自拍 | 色多多污 | 中文字幕一区二区三区乱码不卡 | 中国女人裸体乱淫 | 成人国产视频在线观看 | 成人不卡av | 国产精品免费视频一区二区三区 | 美女色呦呦 | 折磨小男生性器羞耻的故事 | 天堂av免费 | av丝袜在线观看 | 国产制服av | 在线99 | 国产日韩精品在线 | 久久99一区 | 国产一区精品在线观看 | 无码人妻丰满熟妇精品 | 山外人精品影院 | 久久免费看 | 在线视频h | 国产精选中文字幕 | 日韩精品网址 | 免费日本黄色网址 | 国产一区二区亚洲 | 91春色 | 成人无码久久久久毛片 | 欧美日韩综合精品 | 香蕉综合视频 | 欧美精品一区二区不卡 | 亚洲黄色网络 | 国产精品老熟女一区二区 | 日本五十路| 日韩在线视频免费观看 | 丰满人妻老熟妇伦人精品 | 狠狠爱综合| 欧美高清大白屁股ass18 | 青青草原在线免费观看视频 | av性在线 | 午夜免费福利网站 | 99久久国| www色综合| 日韩不卡一二三区 | 五月婷婷中文字幕 | 久久久免费网站 | 日韩在线视频在线观看 | 91精品国自产 | 亚洲欧美精品在线观看 | 天堂网站| 日本少妇ⅹxxxxx视频 | 一区二区色 | 国内精品偷拍视频 | 日本一区二区免费视频 | 国产美女视频一区二区 | 国产女主播喷水视频在线观看 | 天堂久久精品 | 嫩草视频国产 | 天天曰| 97se综合 | 日本成人激情视频 | 欧洲视频一区 | 成年人网站免费视频 | 婷婷视频在线 | 日韩欧美综合久久 | 爆乳2把你榨干哦ova在线观看 | 依人成人网| 国产精品女同一区二区 | 小伸进喷水网站 | 波多野结衣黄色片 | 五月99久久婷婷国产综合亚洲 | 天天干人人干 | 8x8ⅹ国产精品一区二区二区 | 色欧美片视频在线观看 | 免费激情网址 | 国产91在线播放 | 欧美黑粗硬 | 亚洲色图少妇 | 另类小说欧美 | 中文字幕在线观看的网站 | 99热手机在线观看 | 涩涩97| 成人av黄色| 国产午夜精品在线 | xxx视频网站 | 久久久久亚洲精品国产 | 大肉大捧一进一出好爽 | 亚洲m码 欧洲s码sss222 | 欧美精品一区二区三区久久 | 欧美一级黄色录像 | 亚洲日本精品视频 | 成人免费视频观看视频 | 亚洲精品字幕在线 |