FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
363 stars 39 forks source link

富文本编辑器复制拖拽图片 #114

Open FrankKai opened 5 years ago

FrankKai commented 5 years ago

起初想只记录司空见惯的浏览器事件,例如复制,粘贴,剪切等等。但后续由于业务需求,更新为富文本编辑器复制拖拽图片的一次尝试。

FrankKai commented 5 years ago

Paste事件

ClipboardEvent Paste事件只有在一种情况下会触发:选中的内容从clipboard复制到document。 event.clipboardData中存放了来自粘贴板的内容,不仅仅是文字,也可以是文件和图片,clipboardData的的类型是DataTransfer。 demo地址:https://jsfiddle.net/betterbetter/3zgn4b72/

QQ裁剪截图到编辑框 截图到编辑框,可以拿到files,items的类型是file。 e.files[0]

0: File(39272)
lastModified: 1540448538008
lastModifiedDate: Thu Oct 25 2018 14:22:18 GMT+0800 (中国标准时间) {}
name: "image.png"
size: 39272
type: "image/png"
webkitRelativePath: ""

e.items[0]

kind: "file"
type: "image/png"

复制系统图片到编辑框 复制foo.png到编辑框,可以拿到files,items的类型却是string。 e.files[0]

0: File(1068580)
lastModified: 1540450301279
lastModifiedDate: Thu Oct 25 2018 14:51:41 GMT+0800 (中国标准时间) {}
name: "image.png"
size: 1068580
type: "image/png"
webkitRelativePath: ""

e.items[0]

kind: "string"
type: "text/plain"

Drop事件

DragEvent

拖放系统图片到编辑框 拖放foo.png到编辑框,可以拿到files,items的类型是file。 e.files[0]

0: File(1086397)
lastModified: 1534770339506
lastModifiedDate: Mon Aug 20 2018 21:05:39 GMT+0800 (中国标准时间) {}
name: "foo.png"
size: 1086397
type: "image/png"
webkitRelativePath: ""

e.items[0]

kind: "file"
type: "image/png"
FrankKai commented 5 years ago

DataTransfer是一种什么数据格式?

一些关键标准属性

DataTransfer.dropEffect

获得当前选中的"drag""drop"操作的类型,或者设置操作成新的类型。值类型包括none, copy, link, move。

DataTransfer.effectAllowed

所有的允许的操作类型。包括none,copy,copyLink,copyMove,link,move,all或者uninitialized。

DataTransfer.files

包括所有的在data transfer中的可用的本地文件。如果drag操作不涉及拖动文件,这个属性将为空。

DataTransfer.items(只读)

包括了所有drag数据的DataTransferItemList对象。

DataTransfer.types(只读)

在dragstart事件中设置的字符串格式。

一些关键标准方法

DataTransfer.clearData()

清除特定类型的数据,若不传参,则清除所有类型的数据。

DataTransfer.getData()

查询特定类型的数据。

DataTransfer.setData()

为特定类型设置数据。可以覆盖。

DataTransfer.setDragImage()

设置一个拖动图像。

FrankKai commented 5 years ago

clipboardData和dataTransfer区别是什么?

其实从字面意思就可以理解。

举个例子:

FrankKai commented 5 years ago

Document.execCommand()是什么?

语法:

bool = document.execCommand(aCommandName,  aShowDefaultUI, aValueArgument);

只有用户操作,bool才会返回true。不要尝试用这个方法判断浏览器是否支持某个命令,因为它的isTrusted是false。

参数

aCommandName

要执行的命令的DOMString,有很多Command可以执行。

aShowDefaultUI

默认的用户界面是否会被展示。在Mozilla中还未实现。

aValueArgument

有些需要输入值的命令,在这个参数输入值。例如insertImage命令,需要输入image的URL。如果没有参数,那么这个参数为null。

常用的insertImage命令

document.execCommand('insertImage', true, 'http://foo.com/bar.png');

在插入点插入一张图片。需要为image的src属性添加一个URL作为值。与createLink的必须,非必须情况一样,至少需要a single character,可以是空格。

FrankKai commented 5 years ago

formData是一种什么数据格式?

由于是duck typing,所以出现一个新的类型的对象,无外乎是对属性的增删改查,并且在一些特定的方法。那么FormData的crud是什么呢?

FormData.append()

create,update某个属性值。与FormData.set()功能类似。

当我们引入qiniu,oss等第三方云存储平台的时候,可以直接将file传入,sdk会帮助我们去构造FormData并且发送XHR。

FrankKai commented 5 years ago

究极demo

demo地址:https://jsfiddle.net/betterbetter/tgLsowp7/8/

<div id="app">
  <div 
    class="editor"
    @paste="imageImport"
    @drop="imageImport"
    contenteditable>
  </div>
</div>
new Vue({
  el: "#app",
  methods: {
      imageImport(e) {
        e.preventDefault();
         const transfer = e.clipboardData || e.dataTransfer;
         const file = transfer.files[0];
         const xhrData = new FormData();
         xhrData.append('image',file);
         document.execCommand('insertImage',true, "http://ov6jc8fwp.bkt.clouddn.com/D43AA1E7-29E9-4C1B-B615-7D4172907531.png");
         console.log(e);
         // 上传接口,可由node提供,也可由java提供,go也行,python也行,看您心情
    }
  }
})
FrankKai commented 5 years ago

意外收获

浏览器中的clipboard是什么?

Clipboard在用户授权的情况下,具有操作系统的剪贴板的read和write的权限。

Clipboard Interface与Clipboard API区别是什么?

Clipboard API

Clipboard API提供了一种异步读取和写入到操作系统clipboard的能力,从而响应clipboard中的cut,copy,paste命令。在Permission API后面访问剪贴板的内容;在用户不允许的情况下,读取或者修改clipboard中的内容是不被允许的。 Clipboard API是为取代通过document.execCommand()获取clipboard的权限而设计的。

Clipboard Interface(异步粘贴板API)

提供了一个从操作系统的剪贴板读写文本和数据的interface。这是一个Secure context。在Async Clipboard API。 区别:interface可以去调API,这里的API指的浏览器与操作系统交互,一个API可以被浏览器的多个interface调用。

什么是ClipboardEvent Interface(粘贴板事件API)?

代表了剪贴板修改的事件,包括cut,copy,paste事件。在Clipboard Event API。

Clipboard Interface 与 ClipboardEvent Interface区别?

什么是Permission API?

自动拒绝或者允许API权限,询问用户是否拒绝或者允许API权限。