最近寫博客需要插入一些截圖,想着用DataURL會方便點,於是需要一個把圖片轉成DataURL的工具。搜索一番后發現這個功能用HTML就能實現,通過paste事件。
先嘗試在Chrome上實現,Chrome版本 43.0
html
<!DOCTYPE html> <html> <head></head> <body> <textarea id="result" style="width:800px; height:600px; resize:none"></textarea> <script> var body = document.getElementsByTagName('body')[0]; body.addEventListener('paste', function(e){ var clipboard = e.clipboardData; var type = clipboard.items[0].type; if (type.match(/image/)) { var blob = clipboard.items[0].getAsFile(); var file = new FileReader(); file.addEventListener('loadend', function(e){ document.getElementById('result').value = e.target.result; }); file.readAsDataURL(blob); } else { document.getElementById('result').value = "not an image\ntype: " + type + "\n\n"; } }); </script> </body> </html>
給body添加一個paste事件,會在粘貼時觸發,粘貼有關的信息都會隨着e傳入回調函數。e是一個ClipboardEvent,獲取它的clipboardData,就可以通過一系列操作取出數據。
首先檢查一下粘貼數據的類型,如果是圖片則取出Blob對象,再用FileReader去讀取,結果就是DataURL了。
如果不是圖片,直接打印提示信息。
粘貼一段文本的效果:
這里需要注意的是,paste是在粘貼前觸發的,所以文本會在提示信息打印后被粘貼到文本框里(粘貼的默認行為)。如果需要取消這種默認行為,可以用 e.preventDefault()
。
Chrome的代碼在IE上完全無法工作,然后我找到了一個微軟IE的粘貼圖片的演示。
這個演示很有意思,IE可以直接在“編輯器”里粘貼圖片,而且這是由瀏覽器支持的,甚至不需要Javascript。
給div設置一個contenteditable屬性之后,這個div就可以被任意編輯,在其中粘貼的圖片會自動通過img標簽顯示,它的src就是我們要的DataURL,直接獲取就可以了。
這個演示需要IE11(Edge),以下我寫的也一樣。
html
<!DOCTYPE html> <html> <body> <textarea id="result" style="width:800px; height:600px; resize:none"></textarea> <div id="editor" contenteditable="true" style="border:1px solid #ccc"> paste here </div> </body> <script> var editor = document.getElementById('editor'); editor.addEventListener('paste', function(e){ console.log(e); setTimeout("updateDivContent()", 0); }); function updateDivContent(){ for (var i=0;i<editor.childNodes.length;i++) { var node = editor.childNodes[i]; if(node.nodeName == "IMG"){ result = node.src; } } for (var i=0;i<editor.childNodes.length;i++) { editor.removeChild(editor.childNodes[i]); } document.getElementById('result').value = result; } </script> </html>
這里傳給paste回調的e實際上是個DragEvent,不過它沒有包含粘貼的數據(dataTransfer是null),所以並沒有什么用。
如果在回調里獲取不到粘貼的數據,我們便需要在粘貼結束后,再去獲取div里的img標簽,因為粘貼的行為是在回調之后執行的。
這里我通過setTimeout實現在粘貼后執行函數,這種做法看上去很不靠譜(我不知道),不過微軟那個例子里也有類似的寫法。
在updateDivContent里,先獲取img的src,然后清空div,再設置textarea來顯示DataURL。
實際上呢IE這個例子有點舍本逐末的感覺,既然瀏覽器支持這樣的特性,可以把div直接做成一個編輯器,這樣就更方便了。
最后有一個疑問是,微軟的例子里的Blob String到底是什么機制?看上去是把圖片保存到了本地的某個位置,再用那一串字符串去索引?