上篇介绍了一下我从 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 中: