日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
教你如何自定義 Drag 樣式.md

在 web 中,圖片默認(rèn)是可以拖拽的,通常是一個(gè)半透明的預(yù)覽圖(下面簡(jiǎn)稱(chēng)“預(yù)覽圖”),如下:

為永泰等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及永泰網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、永泰網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

這個(gè)預(yù)覽圖是系統(tǒng)自動(dòng)生成的,一般無(wú)法進(jìn)行自定義,但有時(shí)候會(huì)覺(jué)得拖拽的預(yù)覽圖尺寸太大了,不方便放置,例如在這種場(chǎng)景下。

這是一個(gè)拖拽圖片保存的功能,需要將圖片拖拽至指定區(qū)域觸發(fā)保存操作。由于拖拽時(shí)預(yù)覽圖太大,導(dǎo)致放置區(qū)域都被遮住了,茫茫的一片,體驗(yàn)非常不好。

如果預(yù)覽圖的尺寸可以小一點(diǎn),例如這樣:

是不是體驗(yàn)就會(huì)好很多?下面一起來(lái)探討一下。

一、預(yù)覽圖的默認(rèn)尺寸

首先,拖拽預(yù)覽圖的尺寸是和頁(yè)面上圖片的CSS 尺寸相關(guān)聯(lián)的,也就是說(shuō)展示的圖片越大,拖拽的預(yù)覽圖越大。

但是,預(yù)覽圖的大小并不是無(wú)限制的,據(jù)我測(cè)試,預(yù)覽圖的最大尺寸是 400 * 400,比如下方圖片的尺寸是 500 * 500, 但是拖拽出來(lái)的預(yù)覽圖只有 400 * 400,但對(duì)實(shí)際開(kāi)發(fā)而言,這個(gè)尺寸還是過(guò)大。

以上是 MacOS Chrome 下的表現(xiàn)效果,F(xiàn)irefox 表現(xiàn)要好很多,不會(huì)出現(xiàn)預(yù)覽圖過(guò)大的情況。

另外,測(cè)試了一下 Windows Chrome 的表現(xiàn)效果,比較類(lèi)似,只不過(guò)最大尺寸是 200 * 200,表現(xiàn)如下:

二、借助 setDragImage 修改預(yù)覽圖

原生的拖拽只能通過(guò) setDragImage[1] 來(lái)修改預(yù)覽圖,看著好像很強(qiáng)大,實(shí)則非常雞肋,簡(jiǎn)單使用如下:

function dragstart_handler(ev) {
var img = new Image();
img.src = 'example.jpg';
ev.dataTransfer.setDragImage(img, 0, 0);
}

這里指定了這樣一張圖片作為預(yù)覽圖:

需要綁定在 dragstart事件上,這里采用事件委托的方式。

document.addEventListener('dragstart', ev => {
if (ev.target.tagName === 'IMG') {
dragstart_handler(ev)
}
})

效果是這樣的:

為什么是第二次拖拽才出現(xiàn)自定義預(yù)覽呢?這就是雞肋的地方了,官方規(guī)定 example.jpg為一個(gè)已經(jīng)存在的圖片,如果這個(gè)還沒(méi)有創(chuàng)建或者還未加載完成,那么瀏覽器將會(huì)使用默認(rèn)的拖動(dòng)圖片,在第二次拖拽的時(shí)候圖片加載完了,所以才生效??梢哉f(shuō),幾乎所有setDragImage不起作用的情況都是因?yàn)檫@個(gè)原因。

除此之外,還有一個(gè)問(wèn)題,無(wú)法直接指定預(yù)覽圖的大小,例如:

function dragstart_handler(ev) {
var img = new Image();
img.src = 'example.jpg';
img.width = 50;//無(wú)效
img.height = 50;
ev.dataTransfer.setDragImage(img, 0, 0);
}

這樣也是無(wú)效的,內(nèi)存中的圖片會(huì)按原始大小來(lái)展示。

三、指定預(yù)覽圖為頁(yè)面元素

其實(shí),要想修改預(yù)覽圖的大小還可以通過(guò) canvas 渲染原圖,然后修改尺寸再生成圖片,但是 canvas 在渲染圖片時(shí)經(jīng)常會(huì)出現(xiàn)跨域的問(wèn)題,并且 canvas 也有一定的門(mén)檻,所以這里先不采用。

再回過(guò)來(lái)看看官方的語(yǔ)法:

dataTransfer.setDragImage(img | element, xOffset, yOffset);

可以看到,第一個(gè)參數(shù)不僅支持動(dòng)態(tài)創(chuàng)建的圖片,也支持頁(yè)面上實(shí)際存在的元素(頁(yè)面上存在的元素肯定是加載完成的)。

假設(shè)我們將自定義預(yù)覽圖添加在頁(yè)面。


然后將預(yù)覽圖指定為該圖片example.jpg。

ev.dataTransfer.setDragImage(img, 0, 0);

效果如下:

可以看到,拖拽圖片就像拖拽 example.jpg 一樣,而且也可以通過(guò)CSS直接修改尺寸!

#img{
width: 100px;
height: 100px;
}

預(yù)覽圖大小也是跟隨 example.jpg 的。

如果把 example.jpg換成和原始圖相同的鏈接,是不是就相當(dāng)于可以自定義預(yù)覽圖的大小了呢?

現(xiàn)在需要將自定義圖片隱藏起來(lái),畢竟只是借用一下,頁(yè)面上不需要顯示,這里需要一點(diǎn)小技巧了,不能真正的將這個(gè)圖片隱藏起來(lái),比如:

#img{
display: none;
/*或者*/
opacity: 0;
/*或者*/
visibility: none
}

這些方式都不行,由于預(yù)覽圖是跟隨這張自定義圖片的,如果直接隱藏了都會(huì)導(dǎo)致預(yù)覽圖直接消失不見(jiàn)。

這時(shí)采取的方式可以將這張圖片移到視區(qū)之外,比如這樣:

#img{
position: absolute;
top: -9999px;
}

這樣就沒(méi)問(wèn)題了。

實(shí)際工作中,這張圖應(yīng)該是自動(dòng)生成的,而且自動(dòng)獲取當(dāng)前拖拽圖片的鏈接,完整實(shí)現(xiàn)就是。

/* 
* custom_drag_img
* author: xboxyan
*/
const img = document.createElement('img');
img.style = "position: absolute; top: -9999px; max-width: 100px; max-height: 100px;"
document.body.append(img)
document.addEventListener('dragstart', ev => {
if (ev.target.tagName === 'IMG') {
img.src = ev.target.src;
ev.dataTransfer.setDragImage(img, 0, 0);
}
})

可以將這段代碼注入其他地方,試試效果,比如原始效果如下:

注入以上代碼之后的效果如下:

在某些場(chǎng)景下是不是體驗(yàn)好很多呢?

四、自定義預(yù)覽圖樣式

上述預(yù)覽圖不僅可以指定圖片元素,也可以其他元素,比如div,添加一些修飾。




.drag_img{
position: absolute;
top: -9999px;
max-width: 100px;
max-height: 100px;
border: 3px solid yellow;
}

這樣就可以給預(yù)覽圖加上一個(gè)黃色邊框(強(qiáng)調(diào)作用)了。

亦或是通過(guò)偽元素加個(gè)角標(biāo)。

.drag_img::after{
content: '';
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 20px;
background: linear-gradient(-135deg, #f44336 50%, transparent 51%);
}

但是添加CSS濾鏡沒(méi)有生效,仍然是原始樣式:

.drag_img{
position: absolute;
top: -9999px;
max-width: 100px;
max-height: 100px;
filter: sepia(1); /*褐色濾鏡*/
}

這可能跟系統(tǒng)生成預(yù)覽圖的策略有關(guān),無(wú)從得知,也無(wú)法修改

五、完全的自定義方案 draggable-polyfill

其實(shí)上述都只是針對(duì) setDragImage做的一些自定義,本質(zhì)上還是原生預(yù)覽圖,也僅適用于圖片拖拽(但是性能超好),如果想完全自定義拖拽效果,自定義普通可拖拽元素,就必須通過(guò) JS 模擬實(shí)現(xiàn)了。大致思路如下

  1. 去除默認(rèn)的預(yù)覽圖
  2. 復(fù)制一份當(dāng)前目標(biāo)元素,cloneObj
  3. 監(jiān)聽(tīng)拖拽事件,通過(guò) transform 改變cloneObj的位置
  4. 拖拽結(jié)束移除cloneObj

詳細(xì)原理可以參考我之前的一篇文章:實(shí)現(xiàn)一個(gè)美化原生拖拽的draggable-polyfill[2],雖然是自定義實(shí)現(xiàn)的,但是完全不影響原有業(yè)務(wù)拖拽邏輯,這正是 polyfill 的魅力,非常適合原生拖拽實(shí)現(xiàn)的場(chǎng)景。

項(xiàng)目地址:https://github.com/XboxYan/draggable-polyfill(或者訪(fǎng)問(wèn)文章底部「原文鏈接」)[3],非常輕量,100 來(lái)行代碼,不影響業(yè)務(wù)邏輯,非常適合學(xué)習(xí)和時(shí)使用,歡迎 star~

3 年前的老代碼了,最近優(yōu)化了一波,非常實(shí)用,歡迎 star

六、總結(jié)一下

以上就完成了圖片拖拽預(yù)覽圖的自定義,其實(shí)主要用于修改預(yù)覽尺寸,在某些場(chǎng)景下還是挺有用的,這里總結(jié)一些要點(diǎn):

  1. 在拖拽時(shí)產(chǎn)生的預(yù)覽圖是系統(tǒng)生成的,無(wú)法直接修改
  2. 在macOS Chrome下,預(yù)覽圖的尺寸最大為 400 * 400,在某些場(chǎng)景下體驗(yàn)不太友好
  3. setDragImage 可以修改預(yù)覽圖
  4. setDragImage 需要圖片已經(jīng)加載完成才會(huì)生效,否則仍然是默認(rèn)樣式
  5. setDragImage 可以指定頁(yè)面上的其他元素,不僅僅是 img
  6. setDragImage 指定的元素不能真正的隱藏,否則預(yù)覽圖將不可見(jiàn),可以通過(guò)移出到視線(xiàn)之外的方式
  7. 以上方案適用于圖片拖拽,并且自定義的樣式有限
  8. 如果需要完全自定義拖拽,可以采用 draggable-polyfill 方案,歡迎star~

總的來(lái)說(shuō),整體實(shí)現(xiàn)還是非常簡(jiǎn)單的,由于是原生方案,性能就不用說(shuō)了,也不會(huì)影響原有功能,起到了美化的作用,如果有類(lèi)似的需求,就趕緊用起來(lái)吧~

參考資料

[1]setDragImage: https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransfer/setDragImage。

[2]實(shí)現(xiàn)一個(gè)美化原生拖拽的draggable-polyfill: https://segmentfault.com/a/1190000020842646。

[3]https://github.com/XboxYan/draggable-polyfill: https://github.com/XboxYan/draggable-polyfill。


當(dāng)前題目:教你如何自定義 Drag 樣式.md
網(wǎng)頁(yè)鏈接:http://m.5511xx.com/article/cdsspge.html