摘要:最近在實現一個功能,需求如下前提當前頁面無彈窗頁面任意位置執行粘貼讀取剪切板中的截屏數據上傳截圖首先還是從網上找相關的例子。找到了上的專欄文章獲取剪切板內容,控制圖片粘貼。
最近在實現一個功能,需求如下:
前提:當前頁面無彈窗
頁面任意位置執行粘貼
讀取剪切板中的截屏數據
上傳截圖
首先還是從網上找相關的例子。
找到了SF上的專欄文章《js獲取剪切板內容,js控制圖片粘貼》。
于是基于這個,做出了第一版的截圖上傳功能。
由于項目使用的是angularjs,事先已經封裝好一套上傳圖片的辦法,只需要調用 $scope.image = blob,自動就會發送、上傳該文件。
我是半路介入項目的。原來為數不多的幾個js文件實在太大,一個apiService.js就累積了三四千行,各種服務都在這個文件里,主視圖就一個mainController,也是三四千行。
說實話,我真的驚呆了。
所以還是盡量避免修改原來的代碼。
按照我自己習慣,把功能封裝成directive,獨立建一個文件。
代碼如下:(特別鳴謝本期節目的文章)
/** * @description: 截屏上傳 * @author: angusfu1126@qq.com * @date: 2016-03-03 20:59:09 */ app.directive("screenshotOrDragUpload", /*ngInject*/ function($filter) { return { restrict: "A" link: function($scope, iElm, iAttrs, controller) { var imageRegex = /^image//i; // 粘貼截圖事件 document.addEventListener("paste", onPasteHandler, false); // 作用域銷毀的時候解除事件綁定 $scope.$on("$destroy", function() { document.removeEventListener("paste", onPasteHandler); }); /** * 全局蒙版顯示的時候 * 不執行粘貼或者拖拽功能 * 避免和各種彈層ng-show條件太耦合 * 此處使用DOM方法判斷 */ function isMaskShown() { // 項目依賴于jquery return angular.element(".global-mask").is(":visible"); } /** * 根據時間戳命名 */ function generateFileName(user) { return $filter("date")(new Date(), "yyyyMMdd_HH:MM:ss"); } /** * 處理 `ctrl + v` 截圖粘貼事件 */ function onPasteHandler(e) { if (isMaskShown()) return; var clipboardData = e.clipboardData; var ua = window.navigator.userAgent; // 如果無法獲取剪貼板則返回 if (!clipboardData || !clipboardData.items) { return; } // Mac平臺下Chrome49版本以下 // 復制Finder中的文件的Bug Hack掉 // see: https://segmentfault.com/a/1190000004288686 if (clipboardData.items && clipboardData.items.length === 2 && clipboardData.items[0].kind === "string" && clipboardData.items[1].kind === "file" && clipboardData.types && clipboardData.types.length === 2 && clipboardData.types[0] === "text/plain" && clipboardData.types[1] === "Files" && ua.match(/Macintosh/i) && Number(ua.match(/Chrome/(d{2})/i)[1]) < 49 ) { return; } var len = clipboardData.items.length, item = null, blob = null; while (len--) { item = clipboardData.items[len]; if (item.kind == "file") { blob = item.getAsFile(); if (imageRegex.test(blob.type) && blob.size > 0) { blob.name = generateFileName(); // 調用上傳 $scope.image = blob; break; } } } } } }; });
當然,文章不可能就此結束。。。
分割線休息片刻
==============================================================
上述功能只有在Chrome和Safari中有效,但到火狐上面就掛掉了啊。。。
測試一下,給document綁定paste事件,粘貼的時候壓根就讀不到數據。
火狐下面,并沒有clipboardData.items這一項。
o(╯□╰)o
那怎么辦呢?
只能退而求其次。放棄,或者尋求降級的辦法。
就在我覺得無路可走的時候,火狐的一個特點讓我眼前一亮。。。
分別用chrome和firefox打開這個demo試試看,試著用qq截個圖或者在文件夾中復制一張圖片,粘貼在紅色框框里。
有沒有發現,只有在火狐下能把圖粘貼進來?
嗯,解決辦法就在這里了。
其實,demo中的紅色框框是一個有contenteditable屬性的div。
關于contenteditable,此處有張鑫旭大神的博文兩篇,且記在此處備忘:
小tip: 如何讓contenteditable元素只能輸入純文本
div模擬textarea文本域輕松實現高度自適應
firefox下面,是可以把剪切板中的圖片數據粘貼進去的,而chrome下面則不行了。
而項目的輸入框,正好是一個pre標簽加上contenteditable屬性模擬出來的。完美~~~(此處應有金星老師表情包)
好了,在火狐中粘貼截圖之后,右鍵查看一下,是不是像下圖醬紫的?
有木有看到醒目的img標簽?
有木有看到醒目的data:image/png;base64,?
辦法有了。解決方案如下:
監聽keydown事件
檢測輸入框是否為空
非空:不允許粘貼圖片(但我們不能事先判斷數據類型,只能迅速remove掉img元素)
空的:獲取img元素及其src數據,然后迅速移除元素
當然,此處是有坑的。。。
具體坑在哪里呢?看代碼吧。其實我覺得我可能沒完全解決。
if (/firefox/i.test(navigator.userAgent)) { var URL = (window.URL || window.mozURL), supportTransform = URL && window.Blob && window.atob && window.ArrayBuffer && window.Uint8Array, // see http://jsperf.com/blob-base64-conversion convertBase64UrlToBlob = function(urlData) { //去掉url的頭,并轉換為byte var bytes = window.atob(urlData.split(",")[1]); //處理異常,將ascii碼小于0的轉換為大于0 var ab = new ArrayBuffer(bytes.length); var ia = new Uint8Array(ab); for (var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } return new Blob([ab], { type: "image/png" }); }; $("pre").on("keydown", function(e) { var isCtrlV = (e.ctrlKey && e.keyCode == "86"); if (!supportTransform || !isCtrlV) return; var $this = $(this), html = $this.html(), canPasteImage = false; // Notice // 火狐的坑在這里啊啊啊啊 // 只有空的時候才能粘貼圖片 if (!html || html === "
") { canPasteImage = true; } setTimeout(function() { var $imgs = $this.find("img").remove(), data = $imgs.eq(0).attr("src"); if (canPasteImage && data) { var blob = convertBase64UrlToBlob(data); blob.name = generateFileName(); // 調用上傳 $scope.image = blob; } }, 0); }); }
做個筆記: Blob對象和base64字符串的轉換, http://jsperf.com/blob-base64-conversion
目前還沒在IE上測試過,不知道結果如何。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78872.html
摘要:最近在幫人解決下的一些兼容問題。驗證不通過的話,輸入框會加上紅色的邊框。然后妹紙在描述中說的是瀏覽器中,修改密碼頁面,輸入框中不輸入任何字符,輸入框顏色也是紅的我還以為又是哪里的寫得不對呢。最后發現,輸入框好像都帶了個屬性。 因為工作一年多以來,做的工作基本都是和webkit系列打交道。 先是做m站,后來做了兩個app內嵌的hybrid項目,從來只考慮webkit前綴和相關的偽類。 最...
摘要:最近在幫人解決下的一些兼容問題。驗證不通過的話,輸入框會加上紅色的邊框。然后妹紙在描述中說的是瀏覽器中,修改密碼頁面,輸入框中不輸入任何字符,輸入框顏色也是紅的我還以為又是哪里的寫得不對呢。最后發現,輸入框好像都帶了個屬性。 因為工作一年多以來,做的工作基本都是和webkit系列打交道。 先是做m站,后來做了兩個app內嵌的hybrid項目,從來只考慮webkit前綴和相關的偽類。 最...
摘要:背景近幾年直播行業飛速發展,但是由于端這方面功能的長時間缺失,使得直播端以客戶端為主的出現使得網頁也可以成為直播端。通過發送消息到插件調起屏幕共享。的點對點連接的過程為呼叫端給接收端發送一個信息。下面簡單介紹下使用聲網發起直播的流程。 背景 近幾年直播行業飛速發展,但是由于Web端這方面功能的長時間缺失,使得直播端以客戶端為主;WebRTC 的出現使得網頁也可以成為直播端。那么究竟We...
摘要:難在哪里根據上面的標簽需要定位最后一行標簽,以下列出了四種方式,定位的方式多樣并不唯一,使用時根據情況進行解析即可。加入每日一練我們使用并指明標簽內全部文本即可定位。 ...
閱讀 1309·2021-11-04 16:09
閱讀 3509·2021-10-19 11:45
閱讀 2404·2021-10-11 10:59
閱讀 1019·2021-09-23 11:21
閱讀 2770·2021-09-22 10:54
閱讀 1146·2019-08-30 15:53
閱讀 2612·2019-08-30 15:53
閱讀 3484·2019-08-30 12:57