摘要:前言最近項(xiàng)目新增需求用戶能夠拖拽頁面上的圖片文件到文檔。在現(xiàn)有的拖拽事件所提供無法滿足需求的情況下,換一個(gè)思路走嘗試將圖片復(fù)制到剪貼板。只復(fù)制目標(biāo)節(jié)點(diǎn)的子節(jié)點(diǎn),對(duì)于標(biāo)簽,如果不額外包裹一層父元素,無法實(shí)現(xiàn)圖片復(fù)制。
前言
最近項(xiàng)目新增需求:用戶能夠拖拽頁面上的圖片文件到word文檔。
當(dāng)操作瀏覽器里拖拽圖片至別的程序,在word文檔中展示出獲取到的只是圖片的url地址,而非預(yù)期的圖片文件。在現(xiàn)有的拖拽事件所提供api無法滿足需求的情況下,換一個(gè)思路走:嘗試將圖片復(fù)制到剪貼板。
對(duì)于原生js的復(fù)制操作,已有封裝好的庫clipboard.js,但是封裝得太死,無法滿足更多定制化的需求,主要表現(xiàn)在以下兩點(diǎn):
只接受click事件,無法綁定其他事件。
只復(fù)制目標(biāo)節(jié)點(diǎn)的子節(jié)點(diǎn),對(duì)于img標(biāo)簽,如果不額外包裹一層父元素,無法實(shí)現(xiàn)圖片復(fù)制。
參考clipboard.js源碼,了解了實(shí)現(xiàn)原理后(其實(shí)非常簡單!:) ),我們就能自己動(dòng)手封裝一個(gè)復(fù)制方法:
概述 Range對(duì)象Range表示包含節(jié)點(diǎn)和部分文本節(jié)點(diǎn)的文檔片段。最常見的就是用戶在瀏覽器拖動(dòng)鼠標(biāo)選擇的內(nèi)容(user selection)
比如上圖這塊藍(lán)色高亮區(qū)域。
在現(xiàn)代瀏覽器中(IE9以上),你可以通過Document.createRange()方法或者new Range()創(chuàng)建一個(gè)Range對(duì)象;當(dāng)需要獲取user selection時(shí),你應(yīng)該使用window.getSelection()方法獲取Selection對(duì)象。
有點(diǎn)懵?
剛了解了Range對(duì)象,而Selection對(duì)象又是什么?閱讀了文檔之后,還是疑惑它們之間的區(qū)別?
Selection對(duì)象表示用戶的選擇,而Range對(duì)象則表示文檔的連續(xù)部分,與任何視覺表示無關(guān)。一個(gè)Selection對(duì)象幾乎可由0到多個(gè)Range表示出來,當(dāng)然,Range對(duì)象也能獨(dú)立于Selection而被完全的創(chuàng)建和修改。
html部分:
這是一段文字 AAAAAAAAAA BBBBBBBBBB Range
js部分:
var btn1 = document.getElementById("button1"), btn2 = document.getElementById("button2"), input = document.getElementById("input"), rangespan = document.getElementById("range"); var selection = window.getSelection(), range = document.createRange(); btn1.addEventListener("click", function(event) { input.value = selection.toString(); }); btn2.addEventListener("click", function(event) { range.selectNode(rangespan); selection.removeAllRanges(); //刪除包含在selection原本的range,也就是取消用戶選中的范圍 selection.addRange(range); //讓選中部分變成我們自己定義的節(jié)點(diǎn)內(nèi)容 });
演示地址:
https://jsfiddle.net/muvhqcnf...
一點(diǎn)就會(huì) :)
兼容陳舊IE版本Microsoft提供了類似的TextRange接口。
在實(shí)際代碼部分會(huì)展示Microsoft TextRange的基本使用。
execCommand方法允許運(yùn)行命令來操縱可編輯區(qū)域的內(nèi)容。該方法的第一個(gè)參數(shù)是命令的名稱,參數(shù)類型為DOMString。
在這里,我們將利用execCommand方法的copy命令實(shí)現(xiàn)復(fù)制選中的內(nèi)容:
document.execCommand("copy")
execCommand API起源于IE,后來被添加到HTML5(HTML Editing APIs),在各瀏覽器的表現(xiàn)會(huì)有不同。更多請(qǐng)查看文檔。
我們回到前面的演示代碼,將btn1的點(diǎn)擊事件替換成execCommand命令:
btn1.addEventListener("click", function(event) { //input.value = selection.toString(); document.execCommand("copy"); });
拖動(dòng)鼠標(biāo)選擇文字,點(diǎn)擊按鈕后看看能粘貼出什么:)
復(fù)制圖片功能的具體實(shí)現(xiàn) 封裝可以兼容ie的getSelect方法還記得前面的例子里,我們通過range的selectNode(node)方法獲取節(jié)點(diǎn), 再使用selection的removeAllRanges()方法和addRange(range)將節(jié)點(diǎn)替換我們獲取的節(jié)點(diǎn)。在這里,我們同樣可以這樣選中我們目標(biāo)的img節(jié)點(diǎn):
const getSelect = targetNode => { if (window.getSelection) { //chrome等主流瀏覽器 var selection = window.getSelection(); var range = document.createRange(); range.selectNode(targetNode); selection.removeAllRanges(); selection.addRange(range); } else if (document.body.createTextRange) { //ie var range = document.body.createTextRange(); range.moveToElementText(targetNode); range.select(); } }派發(fā)事件
為了不浪費(fèi)性能,我們使用事件委托到希望被復(fù)制的節(jié)點(diǎn)上。這里對(duì)傳入的nodeName進(jìn)行處理,方便自由的控制被復(fù)制一個(gè)或多個(gè)節(jié)點(diǎn)類型。默認(rèn)為。
const clipboardHandler = (nodeName, event) => { event = event || nodeName; //不傳參時(shí) const type = Object.prototype.toString.call(nodeName).replace(/[objects|]/g, ""); const target = event.target || event.srcElement; var result = false; switch (type) { case "String": result = (target.nodeName.toLowerCase() === nodeName); break; case "Array": result = nodeName.some(item => target.nodeName.toLowerCase() === item); break; case "Object": nodeName = null; default: result = (target.nodeName === "IMG"); } if (result) { //調(diào)用之前封裝好的getSelect方法 getSelect(target); document.execCommand("copy"); } }
調(diào)用:
[element].addEventListener("mousedown", clipboardHandler); //預(yù)備拖動(dòng)圖片按下鼠標(biāo)時(shí)執(zhí)行復(fù)制
傳遞參數(shù)(字符串或數(shù)組):
var [somename]Handler = clipboardHandler.bind(null, [nodeName]); [element].addEventListener([eventType],[somename]Handler);
完整代碼演示地址:
已驗(yàn)證在chrome和ie8上可行(ie8需要對(duì)es6語法與bind和addEventListener方法進(jìn)行pollyfill)
希望能夠幫助到你:)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95425.html
摘要:由于我們的富文本輸入框比較簡單,所以只需要處理兩類數(shù)據(jù)即可,其一是普通的文本類型數(shù)據(jù),包括表情其二則是圖片類型數(shù)據(jù)。 最近折騰 Websocket,打算開發(fā)一個(gè)聊天室應(yīng)用練練手。在應(yīng)用開發(fā)的過程中發(fā)現(xiàn)可以插入 emoji ,粘貼圖片的富文本輸入框其實(shí)蘊(yùn)含著許多有趣的知識(shí),于是便打算記錄下來和大家分享。 倉庫地址:chat-input-box預(yù)覽地址:https://codepen.io...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過一定長度的文字就添加版權(quán)信息作者鏈接來源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過一定長度的文字就添加版權(quán)信息作者鏈接來源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
摘要:取消默認(rèn)的復(fù)制事件被復(fù)制的文字等下插入防知乎掘金復(fù)制一兩個(gè)字則不添加版權(quán)信息超過一定長度的文字就添加版權(quán)信息作者鏈接來源掘金著作權(quán)歸作者所有。以上參考資料高程操作剪貼板網(wǎng)頁上如何實(shí)現(xiàn)禁止復(fù)制粘貼以及如何破解原生實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...
摘要:設(shè)定元素的屬性為絕對(duì)。將當(dāng)前選中區(qū)復(fù)制到剪貼板并刪除之。插入隱藏控件覆蓋當(dāng)前選中區(qū)。減少選中區(qū)所在格式化塊的縮進(jìn)。傳遞整數(shù)將顯示用戶界面,整數(shù)將跳過它。方法受到的影響會(huì)閃爍。 document.execCommand()方法處理Html數(shù)據(jù)時(shí)常用語法格式如下:document.execCommand(sCommand[,交互方式, 動(dòng)態(tài)參數(shù)]) 其中:sCommand為指令參數(shù)(如下例...
閱讀 2011·2023-04-25 16:53
閱讀 1455·2021-10-13 09:39
閱讀 619·2021-09-08 09:35
閱讀 1652·2019-08-30 13:03
閱讀 2133·2019-08-30 11:06
閱讀 1842·2019-08-30 10:59
閱讀 3199·2019-08-29 17:00
閱讀 2300·2019-08-23 17:55