日韩性视频-久久久蜜桃-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实现更好的拖拽功能的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 福利视频在线看 | 亚洲码国产精品高潮在线 | 婷色| 欧美成人吸奶水做爰 | 91在线观看免费高清完整版在线观看 | 伊人天天操 | 91av免费 | 亚洲视频一二三 | 成人一区二区三区在线 | 丁香六月五月婷婷 | 黄色小说视频网站 | 国产午夜大地久久 | 喷水了…太爽了高h | 日韩天堂网| 2022精品国偷自产免费观看 | 一区二区在线精品 | 日本三级韩国三级三级a级按摩 | 亚洲制服另类 | 久久五月天婷婷 | 久久久久久久综合色一本 | 日韩国产免费 | 欧美日韩a√ | 超碰人人人人人人人 | 成人免费精品 | 国产三级网站 | 日韩欧美精品一区 | 日韩国产欧美在线观看 | 国产无遮挡免费观看视频网站 | jizzjizz免费 | 国产香蕉尹人视频在线 | 精品中文字幕视频 | 国产美女免费视频 | 欧美三级网站 | 亚洲综合一区中 | 成人久久在线 | 激情成人综合 | 美腿丝袜亚洲综合 | 90岁老太婆乱淫 | 亚洲一级Av无码毛片久久精品 | 黄色一级片欧美 | 一女被多男玩喷潮视频 | 麻豆久久久9性大片 | 国产精品亚洲无码 | 欧美肉大捧一进一出免费视频 | 久久久99精品 | caoporn视频在线| 亚洲一区二区免费在线观看 | 99爱这里只有精品 | 国产一区二区三区电影在线观看 | 青青青在线视频免费观看 | 欧美成人激情在线 | 欧美视频在线观看视频 | 超碰夫妻 | 美女视频黄a视频全免费观看 | 男女午夜影院 | 神马午夜麻豆 | 精品国产一区二区三区无码 | 久热精品视频在线 | 空姐吹箫视频大全 | 中文字幕亚洲激情 | a级黄色影院 | 久久久噜噜噜久久 | 四季av在线一区二区三区 | 中文字幕影院 | www.xxx.日本 | 亚洲伦理在线播放 | 成人av网站在线播放 | 美女扒开粉嫩的尿囗给男生桶 | 国产精品自拍区 | 美女三级网站 | 欧美自拍亚洲 | 国产精品伦一区二区三级古装电影 | 国产 日韩 欧美 精品 | 日韩av在线播 | 欧美黄色大片免费观看 | 亚洲最大激情网 | 欧美一区二区高清视频 | 久艹在线 | 成人看片在线 | 91欧美激情一区二区三区成人 | 五月婷六月| 中文字幕无码毛片免费看 | 亚洲va韩国va欧美va精品 | 婷婷国产在线 | 天堂а√在线中文在线鲁大师 | 撸啊撸av| 亚洲做受高潮 | 亚洲日本欧美精品 | 日本sm调教—视频|vk | 男人的天堂亚洲 | 伊人88| 国产九九在线 | 欧美性生活一区二区三区 | 伊人网影院 | 伊人福利在线 | 欧美精品久久天天躁 | 一区二区三区视频在线观看 | 真人一及毛片 | 亚洲黄色激情视频 |