Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
FrankKai opened this issue Oct 23, 2018 · 7 comments
Open

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

FrankKai opened this issue Oct 23, 2018 · 7 comments
Labels

Comments

@FrankKai
Copy link
Owner

FrankKai commented Oct 23, 2018

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

  • Paste事件,Drop事件
  • DataTransfer是一种什么数据格式?
  • clipboardData和DataTransfer区别是什么?
  • Document.execCommand()是什么?
  • formData是一种什么数据格式?
  • 究极demo
  • 意外收获
@FrankKai
Copy link
Owner Author

FrankKai commented Oct 23, 2018

Paste事件

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

  • 事件类型
    e.type: "paste"

  • 位于e.srcElement.value(需要用console.dri(e.srcElement);查看)。
  • 数据流
    e.clipboardData
    • dropEffect: "none"
    • effectAllowed: "uninitialized"
    • files: FileList {0: File(39272), length: 1}
    • items: DataTransferItemList {0: DataTransferItem, length: 1}

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

  • 事件类型
    e.type: "drop"

  • 没有值。
  • 数据流
    e.dataTransfer
    • dropEffect: "none"
    • effectAllowed: "all"
    • files: FileList {0: File(1086397), length: 1}
    • items: DataTransferItemList {0: DataTransferItem, length: 1}

拖放系统图片到编辑框
拖放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
Copy link
Owner Author

FrankKai commented Oct 23, 2018

DataTransfer是一种什么数据格式?

  • DataTransfer对象用来存储dragged数据,也就是"拖"和"放"的数据。
  • 可以存储一个或者多个数据项,一个数据项包含一个或多个数据类型。
  • 它是drag events对象的一个属性,也就是event.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
Copy link
Owner Author

FrankKai commented Oct 24, 2018

clipboardData和dataTransfer区别是什么?

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

  • clipboardData 这是来自剪贴板的数据。
  • dataTransfer 这是来自转换的数据。

举个例子:

  • 剪贴板上有图片,文字,复制到contenteditable为true的div中的时候,event对象的数据存储在event.clipboardData。
  • 从操作系统桌面拖动图片,放入浏览器的contenteditable为true的div中的时候,evnet对象的数据存储在event.dataTransfer。

@FrankKai
Copy link
Owner Author

FrankKai commented Oct 25, 2018

Document.execCommand()是什么?

  • 当HTML document被切换到designMode,document对象暴露了一个execCommand方法运行命令。
  • 这个命令可以操作当前的可编辑区域,例如form的inputs或者contentEditable元素。
  • 大多数的命令会影响到document的selection,例如bold,italics等等,比如插入一个新元素(添加一个link),或者影响一整行(缩进)。
  • 使用contentEditable,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
Copy link
Owner Author

FrankKai commented Oct 25, 2018

formData是一种什么数据格式?

  • FormData接口提供了一种:轻松地构建一个key/value关系的表单和它们的值,关键是,可以非常轻松地通过XMLHttpRequest.send()方法发送出去。
  • 若encoding的type为"multipart/form-data",它的格式与表单一样。
  • 可以通过for...of遍历FormData类型的数据。
  • 可以在Web Workers中使用。

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

FormData.append()

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

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

@FrankKai
Copy link
Owner Author

FrankKai commented Oct 26, 2018

究极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 FrankKai changed the title 一些常见的浏览器事件 富文本编辑器复制拖拽图片 Oct 26, 2018
@FrankKai
Copy link
Owner Author

意外收获

  • 浏览器中的clipboard是什么?
  • Clipboard Interface与Clipboard API区别是什么?
  • 什么是ClipboardEvent Interface(粘贴板事件API)?
  • Clipboard Interface 与 ClipboardEvent Interface区别?
  • 什么是Permission API?

浏览器中的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调用。

  • Clipboard API
    权限。不仅仅是读写,复制粘贴剪切,还包括了授权等操作。与操作系统的剪贴板之间进行通信的手段。
  • Clipboard Interface
    功能。Clipboard Interface继承EventTarget interface,从浏览器粘贴板和操作系统剪贴板读写二进制数据,重点是read(),readText(),write(),writeText(),也就是"读写"。

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

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

Clipboard Interface 与 ClipboardEvent Interface区别?

  • Clipboard Interface继承EventTarget interface,从浏览器粘贴板和操作系统剪贴板读写二进制数据,重点是read(),readText(),write(),writeText(),也就是"读写"。
  • ClipboardEvent继承Event,获取cut,copy,paste等事件对象,重点是cut,copy,paste,也就是"复制,粘贴,剪切"。

什么是Permission API?

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

@FrankKai FrankKai added the HTML label Mar 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant