上篇介紹了一下我從Typora中學到的Clipboard妙用:我們從網頁複製文字時,剪下板中會塞入兩種格式的資料:純文字和富文字。當我們貼上到其他編輯器時,文字編輯器會使用純文字資料,富文字編輯器會使用富文字資料(Typora中會把對應的文字提取成MarkDown格式)。
具體內容和簡單的程式碼實現可以檢視:我從Typora中學到的Clipboard妙用.md
Typora中圖片處理方式
經常使用Typora的人應該都知道Typora對於處理圖片也有著優秀的使用體驗,當插入圖片時,你可以指定圖片儲存方式:
當我們插入圖片時,上傳服務會把剪下板中的圖片或拖拽的圖片自動上傳,替換成網路地址。這樣當你傳送文件給別人時或者釋出文件到部落格時,不會因為文件在本地而無法檢視。
我自己也寫了一個小工具:file-uploader-cli ,可以處理檔案上傳到對應的儲存服務,比如github
、ftp
、物件儲存等,可以訪問github地址檢視具體的配置方法(uPic和Picgo也支援Typora)。
對於自定義上傳服務,當有圖片插入時,Typora會呼叫上傳服務並傳入檔案路徑,上傳服務在控制檯列印上傳結果即可。
讀取剪下板中圖片資料
我們還是在控制檯中進行快速測試,開啟任意網頁,在element皮膚中找到任意標籤新增contenteditable屬性,當前標籤就變成可編輯元素了。
<p contenteditable>
xxxx
</p>
控制檯中執行程式碼:
document.addEventListener('paste', function(e){
console.log(e)
const items = e.clipboardData.items;
console.log(items)
const fileList = e.clipboardData.files
console.log(fileList)
for(let i=0;i< items.length;i++){
console.log(items[i])
let f = items[i].getAsFile()
console.log(f)
}
e.preventDefault();
})
本地檔案
複製本地檔案(可以是圖片或者其他格式檔案),並在標籤中執行貼上操作:
從上圖可以看出,從clipboardData中取出圖片資料有兩種方式:
- e.clipboardData.items,是一個DataTransferItemList型別資料,每個元素是一個DataTransferItem型別,可以通過DataTransferItem.getAsFile()獲取到File物件
- e.clipboardData.files 是一個FileList, 每個元素是一個File
只有當貼上的是本地檔案時,DataTransferItem.getAsFile才可以獲取到資料,否則為null。
網路圖片
當複製的資料是網路圖片時,分為兩種情況:
- 只包含網路圖片
- 包含網路圖片和文字
當複製的是網路圖片(從網頁直接右鍵複製圖片)時,clipboard會得到兩種資料:text/html
和image/png
。具體可以參考:我從Typora中學到的Clipboard妙用.md
包含網路圖片和文字時,clipboard會得到:text/plain
和text/html
。
所以對於包含網路圖片的兩種方式,在paste事件中獲取到的資料也是不同的:
獲取圖片檔案
從上面的資訊我們可以瞭解到:只有當貼上的為本地影像和網路圖片時,我們可以通過DataTransferItem.getAsFile獲取到圖片物件;當包含文字時可以通過DataTransferItem.getAsString獲取到純文字和富文字資料。
Typora是如何處理圖片資料的
貼上圖片到Typora
如果是本地檔案,Typora會根據偏好設定中的圖片設定進行儲存:
- 當選擇“上傳服務”時,會將本地圖片地址傳給自定義的圖片上傳服務,如果上傳成功則替換成網路地址;如果上傳失敗則保持本地圖片的引用。
- 如果選擇了其他配置,則會複製圖片到對應配置的資料夾下。
如果是剪下板中的非本地圖片(比如截圖複製),會先儲存成本地檔案,再進行上傳或複製。
如果是富文字資料,會直接進行渲染(未勾選對網路位置的圖片應用上述規則
)。
拖拽圖片到Typora
Typora支援paste圖片自動上傳,也支援拖拽圖片上傳,我們可以通過Drop Event獲取到File物件
document.addEventListener('drop', function(e){
console.log(e)
const items = e.dataTransfer.items;
console.log(items)
const fileList = e.dataTransfer.files
console.log(fileList)
e.preventDefault();
})
拖拽資料儲存在DragEvent.dataTransfer中: