canvas项目内复制粘贴及自定义菜单复制粘贴实现

简介: 一、 产品视角下复制粘贴需要解决的问题复制粘贴时,需要静默复制(剪切板内不会看到复制的具体内容, 同miro)统一自定义鼠标复制粘贴和键盘复制粘贴内容实现外部内容也可以粘贴到内部

一、 产品视角下复制粘贴需要解决的问题

  1. 复制粘贴时,需要静默复制(剪切板内不会看到复制的具体内容, 同miro)
  2. 统一自定义鼠标复制粘贴和键盘复制粘贴内容
  3. 实现外部内容也可以粘贴到内部

二、复制粘贴实现方式及分析

复制粘贴代码实现大概分为以下三种方式

  1. Document.execCommand 方法
  1. document.execCommand('copy') 复制命令
  2. document.execCommand('paste') 粘贴命令
  3. 缺点:
  1. safari 不支持
  2. 无法自定义头, 无法控制其写入剪切板是否可见
  3. 同步操作,大量复制可能出现一些卡顿问题
  1. 优点:
  1. 可以触发浏览器的 "copy事件"
  1. 异步的 Clipboard API navigator.clipboard
  1. navigator.clipboard.write 写入剪切板
  2. navigator.clipboard.read 读取剪切板
  3. 缺点:
  1. 只有安全模式可以使用,http模式无法支持
  2. 无法自定义头, 无法控制其写入剪切板是否可见
  1. 优点:
  1. 可以异步读写
  2. 设计更合理,使用方便
  1. 浏览器默认复制粘贴的copy、paste 事件。 e.clipboardData
  1. 事件对象的clipboardData属性包含了剪贴板数据。它是一个对象,有以下属性和方法。
  2. Event.clipboardData.setData(type, data) 修改剪贴板数据,需要指定数据类型
  3. Event.clipboardData.getData(type) 获取剪贴板数据,需要指定数据类型
  4. Event.clipboardData.clearData([type]) 清除剪贴板数据,可以指定数据类型
  5. 优点:
  1. 可以自定义数据类型, 自定义的数据类型只在当前应用内粘贴可见,可以有效保护复制内容
  1. 缺点: 只有原生浏览器事件才可以调用 e.clipboardData, 自定义的鼠标复制粘贴事件无法触发该事件, 但是可以通过 调用document.execCommand('copy') 间接的触发浏览器的onCopy事件,从而间接拿到e.clipboardData 对其进行自定义类型, 局限是safari无法触发, document.execCommand('paste') 无法触发

技术选择

由于第一种和第二种复制粘贴的方式无法自定义复制粘贴的数据类型, 无法解决上述产品视角的问题:

A. 无法设置自定义数据类型,剪切板内会泄漏元素信息

B. 不设置自定义数据类型, 用户复制我们系统中再去其他地方粘贴,会有大量匪夷所思的文本, 用户角度为乱码, 对用户造成理解困扰

三、 键盘Ctrl+C\Ctrl+V 实现思路

1、 监听document上的copy事件、paste事件。 在e.clipboardData 上获取剪切板内的信息, 分别处理外部粘贴,和内部元素粘贴, 将内部复制的元素设置自定义数据类型,粘贴时通过自定义数据类型获取    细节详见代码 onCopy、onPaste 方法

2、阻止默认事件

四、鼠标复制粘贴 实现

1、由于鼠标的复制粘贴为自定义的菜单。 无法拿到系统默认的event.clipboardData 无法设置自定义数据类型, 之前方案是鼠标单独维护了一套复制粘贴逻辑, 问题是无法统一鼠标和键盘的复制粘贴是两套单独的逻辑和结果。

2、其间为了解决鼠标的复制粘贴和键盘的复制粘贴两套的逻辑,分别尝试了,在鼠标复制阶段, 将代码写入浏览器缓存, 写入内存, 等多种方式, 遇到的最大问题是, 无法解决外部复制的内容, 与鼠标复制内部元素的时间先后顺序问题, 产生异常bug

3、幸运的是,通过调研,查看文档, 发现在鼠标调用document.execCommand('copy') 时, 会触发document的copy回调事件, 从而可以成功拿到event.clipboardData设置自定义数据类型, 从而统一鼠标和键盘的复制, 不幸的是, 该方法存在兼容性问题, 在safari 浏览器该事件还是无法直接使用。 而且直接脚本执行 document.execCommand('paste') 各浏览器也无法支持。 所以当前鼠标复制粘贴的方式是, 禁用鼠标右键粘贴, 在safari浏览器中, 禁用鼠标复制粘贴。

4、竞品 miro 中,同样遇到了此类问题,在safari浏览器中同样禁用了鼠标复制粘贴, 在其他浏览器中,禁用了鼠标粘贴

五、画板内复制粘贴实现细节

复制

  • 1、 判断条件当前聚焦在画板内,并且target不是input
  • 2、通过 canvas.getActiveObjects() 拿到选择的元素、判断要复制的元素不是箭头、文本框
  • 3、遍历选中的元素 分别处理 连线 画板 细节 obj.toJSON() 序列化处理元素
  • 4、写入剪切板,自定义写入类型 e.clipboardData.setData('teamind-copy-data', JSON.stringify(jsonArr))
  • 5、组织onCopy默认事件 e.preventDefault()

粘贴

  • 1、判断条件, 鼠标聚焦在当前画板上、非只读模式、非AreaSelection模式、target 不是多文本、input、noPasteUnput
  • 2、处理 event.clipboardData.items 对象, 通过遍历 分别处理外部剪贴板内容 file 和 text、处理内部 teamind-copy-data 类型数据
  • 3、处理文本: 创建一个Textbox canvas添加该元素双击选中、添加到撤销回退内、发送socket消息
  • 4、处理file: 判断图片大小,文件名大小, 调用上传图片方法 uploadImage(file, mouseX, mouseY)
  • 5、判断内部元素 调用方法 pasteObjArr(objArr, new fabric.Point(mouseX, mouseY))

六、补充

/**
 * @param {*} linkText 要复制的文本内容
 * @param {*} callback 复制成功的回调方法
 * 兼容问题
 * navigator.clipboard 在不安全情况(非https)下无法使用,以及用户关闭浏览器权限
 * document.execCommand('copy') 兜底方案 在safari一些版本无法正常使用
 */
export function copyToClipboard(text: string): Promise<string> {
  return new Promise((resolve, reject) => {
    // 是否降级使用
    const isFallback = !navigator.clipboard
    if (!isFallback) {
      navigator.clipboard
        .writeText(text)
        .then(
          () => {
            resolve(text)
          },
          () => {
            copy(text)
            resolve(text)
          }
        )
        .catch(() => {
          reject(text)
        })
    } else {
      copy(text)
      resolve(text)
    }
  })
}
// 降级复制
function copy(text: string) {
  const textarea = document.createElement('textarea')
  document.body.appendChild(textarea)
  // 隐藏此输入框
  textarea.style.display = 'none'
  // 赋值
  textarea.value = text
  // 选中
  textarea.select()
  // 复制
  document.execCommand('copy', true)
  // 移除输入框
  document.body.removeChild(textarea)
}

相关文章
|
5月前
设置VSCode代码编辑器右侧的Minimap代码缩略图滚动条切换显示、隐藏的快捷键Alt+M
设置VSCode代码编辑器右侧的Minimap代码缩略图滚动条切换显示、隐藏的快捷键Alt+M
|
小程序 API
微信小程序如何点击按钮,复制文本到粘贴板
微信小程序如何点击按钮,复制文本到粘贴板
微信小程序如何点击按钮,复制文本到粘贴板
|
5月前
让VSCode的快捷键切换为WebStorm/IDEA的快捷键、修改颜色主题(深色模式)、文件图标主题
让VSCode的快捷键切换为WebStorm/IDEA的快捷键、修改颜色主题(深色模式)、文件图标主题
|
C语言 C++
【VS使用】如何换VS2022背景颜色和分屏观看多文件,还有快捷复制粘贴?
【VS使用】如何换VS2022背景颜色和分屏观看多文件,还有快捷复制粘贴?
310 0
【VS使用】如何换VS2022背景颜色和分屏观看多文件,还有快捷复制粘贴?
|
C#
wpf 复制/剪切到本地系统剪切板中以供右键粘贴用
原文:wpf 复制/剪切到本地系统剪切板中以供右键粘贴用   http://www.cnblogs.com/yhdkzy/archive/2012/11/27/2790655.html   ///         /// 复制或剪切文件到剪切板         /// ...
1246 0
|
Android开发
autojs对话框修改样式
牙叔教程 简单易懂
281 0
“想玩点花式?” 试试快捷键操作编辑器吧(Unity3D)
在使用Unity中可能需要使用快捷键执行一些操作,或者修改Unity自带的快捷键,接下来就看一下,如何设置自定义快捷键吧
解决Typora打开后没反应,一片空白,无法编辑的问题
解决Typora打开后没反应,一片空白,无法编辑的问题
|
API 图形学 Android开发
Unity复制粘贴剪切板各平台源码
Unity直接复制粘贴剪切板一句代码。 本文提供全流程,中文翻译。 助力快速完成 Unity 复制粘贴的实现 为初学者节省宝贵的时间,避免采坑! 现实测,在2018 、2019版本后 直接用一个 API 即可实现 GUIUtility.systemCopyBuffer Chinar测试 安卓 与PC 端 尚未发现任何问题 例如:直接复制一些信息,让玩家可以直接粘贴的方式,分享给好友。
3254 0
|
Web App开发 JavaScript
点击复制内容到剪切板并打开微信
#biao1{ display: none !important; } 444444564564 function copyUrl2() { var Url2=document.
2917 0