用 js 的 selection range 操作選擇區(qū)域內(nèi)容和圖片
先放上最后的效果,這是點(diǎn)擊圖片以前:

這是點(diǎn)擊圖片以后:

非常清晰,一目了然,就算是小白用戶(hù)也明白發(fā)生了什么。挺好的。
最近在做編輯器相關(guān)的東西,遇到一個(gè)需求,用戶(hù)在編輯器中插入或者粘貼的圖片要支持點(diǎn)擊以后,可以按 Backspace 鍵或者 Delete 鍵刪除掉。
剛開(kāi)始拿到這個(gè)需求的想法是調(diào)用編輯器自帶的刪除圖片方法刪掉圖片,但后來(lái)查看源碼發(fā)現(xiàn)這個(gè)方法是編輯器內(nèi)部方法,并沒(méi)有暴露出來(lái),于是第一個(gè)思路走不通了。
第二個(gè)思路是在編輯器的頂層容器里監(jiān)聽(tīng) keyup 事件,然后判斷是否是兩個(gè)刪除鍵,如果是就攔截,然后找到當(dāng)前點(diǎn)擊的圖片,手動(dòng)刪掉。
實(shí)際上這也是行不通的,原因有二。首先,這個(gè)刪除是沒(méi)法阻止的,因?yàn)槭录谋O(jiān)聽(tīng)是在頂層父元素里,這時(shí)候阻止其實(shí)是阻止掉事件在頂層容器上的效果,而不是在發(fā)生元素上的效果。所有涉及到事件冒泡的地方,在父容器上阻止效果都是不能達(dá)到目的的,只能在事件最開(kāi)始發(fā)生的元素上阻止。
然后,當(dāng)按下刪除鍵的時(shí)候,之前點(diǎn)擊的圖片已經(jīng)不是點(diǎn)擊狀態(tài)了,已經(jīng)拿不到了。因?yàn)槿∠x擇在前,刪除在后。
后來(lái)忽然意識(shí)到,想要的效果其實(shí)就是點(diǎn)擊圖片的時(shí)候選中圖片,就像用戶(hù)自己選中網(wǎng)頁(yè)中一段內(nèi)容那樣選中那張圖片就好了。頁(yè)面上點(diǎn)擊一個(gè)圖片默認(rèn)是沒(méi)有效果的,我要做的僅僅是點(diǎn)擊時(shí)候選中這個(gè)圖片就可以了。這樣做的好處是,當(dāng)用戶(hù)點(diǎn)擊圖片選中以后,如果點(diǎn)刪除鍵,無(wú)論是 Backspace 還是 Delete 鍵都可以刪除;而且如果用戶(hù)不像刪除,直接點(diǎn)擊別的地方,或者按下上下左右箭頭就可以取消選擇,這和用戶(hù)平時(shí)的操作體驗(yàn)是一樣的,根本沒(méi)有什么副作用。
selection 是 HTML5 的新接口,是 window 的一個(gè)方法,用法是 window.getSelection().
取得 selection 以后,要把當(dāng)前圖片加入到選取中,selection 有一個(gè) Selection.selectAllChildren() 方法,但這個(gè)方法只能選中元素的全部子元素,而我們要選中的是 img 元素自身,img 元素也沒(méi)有子元素。于是繼續(xù)在 selection 的方法中看看有沒(méi)有別的長(zhǎng)的像的方法,果然,找到了 Selection.addRange() 看這長(zhǎng)相一看就很像我們要找的人。addRange 方法需要傳入一個(gè) range 對(duì)象,range是啥呢?
平時(shí)在頁(yè)面上選擇東西都是鼠標(biāo)咔一下框一大片,但如果在編輯器里,其實(shí)是可以選擇好幾個(gè)片段的,一般按住 Ctrl / Control 鍵就可以多處選擇。我猜這個(gè) selection 就類(lèi)似于選中的所有區(qū)域,range 就類(lèi)似于每一個(gè)單獨(dú)的選中的片段,先這么理解。
繼續(xù)往下看,發(fā)現(xiàn) range 有一個(gè) Range.selectNode() 方法,這不正是我要找的人嗎?先創(chuàng)建一個(gè) range 對(duì)象,let range = document.createRange() createRange 是 document 的方法,然后講當(dāng)前圖片插入 range,再把 range 插入 selection 中即可。代碼如下:
let checkClickImg = function(e) {
let target = e.target;
if (target.nodeName.toLowerCase() === 'img') {
// 刪除之前所有的選區(qū)
window.getSelection().removeAllRanges();
let selection = window.getSelection();
let range = document.createRange();
range.selectNode(target);
selection.addRange(range);
}
}
這個(gè)實(shí)現(xiàn)方法的最大優(yōu)點(diǎn)在于利用瀏覽器原生自帶的功能,這樣就和用戶(hù)的操作習(xí)慣保持一致,不會(huì)有任何的突兀。選中的效果很明顯,而且選中以后無(wú)論是刪除,還是取消,都跟之前習(xí)慣一致,都很容易,更要的是這些操作不用再寫(xiě)代碼了啊,因?yàn)槭菫g覽器原生自帶的功能。
嗯,算是比較完美了。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
使用JS判斷移動(dòng)端手機(jī)橫豎屏狀態(tài)
本文通過(guò)js和cas代碼分別給大家介紹了移動(dòng)端判斷手機(jī)橫豎屏狀態(tài)的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-07-07
js中的異步獲取到的數(shù)據(jù)到底能不能賦值給一個(gè)全局變量問(wèn)題
這篇文章主要介紹了js中的異步獲取到的數(shù)據(jù)到底能不能賦值給一個(gè)全局變量問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
微信小程序復(fù)選框?qū)崿F(xiàn)多選一功能過(guò)程解析
這篇文章主要介紹了微信小程序復(fù)選框?qū)崿F(xiàn)多選一功能過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
p5.js臨摹動(dòng)態(tài)圖形實(shí)現(xiàn)方法詳解
這篇文章主要為大家詳細(xì)介紹了p5.js臨摹動(dòng)態(tài)圖形的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
JS基于ES6新特性async await進(jìn)行異步處理操作示例
這篇文章主要介紹了JS基于ES6新特性async await進(jìn)行異步處理操作,結(jié)合實(shí)例形式分析了async await進(jìn)行異步處理操作的相關(guān)原理、步驟與注意事項(xiàng),需要的朋友可以參考下2019-02-02
微信小程序?qū)崿F(xiàn)藍(lán)牙設(shè)備搜索及連接功能示例詳解
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)藍(lán)牙設(shè)備搜索及連接功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
解析dom中的children對(duì)象數(shù)組元素firstChild,lastChild的使用
以下是對(duì)dom中的children對(duì)象數(shù)組元素firstChild,lastChild的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下2013-07-07
javascript 數(shù)字格式化輸出的實(shí)現(xiàn)代碼
這篇文章主要是對(duì)javascript中數(shù)字格式化輸出的實(shí)現(xiàn)代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12

