资讯专栏INFORMATION COLUMN

JS实现将图片复制到剪贴板

MageekChiu / 1950人阅读

摘要:前言最近项目新增需求用户能够拖拽页面上的图片文件到文档。在现有的拖拽事件所提供无法满足需求的情况下,换一个思路走尝试将图片复制到剪贴板。只复制目标节点的子节点,对于标签,如果不额外包裹一层父元素,无法实现图片复制。

前言

最近项目新增需求:用户能够拖拽页面上的图片文件到word文档。
当操作浏览器里拖拽图片至别的程序,在word文档中展示出获取到的只是图片的url地址,而非预期的图片文件。在现有的拖拽事件所提供api无法满足需求的情况下,换一个思路走:尝试将图片复制到剪贴板

对于原生js的复制操作,已有封装好的库clipboard.js,但是封装得太死,无法满足更多定制化的需求,主要表现在以下两点:

只接受click事件,无法绑定其他事件。

只复制目标节点的子节点,对于img标签,如果不额外包裹一层父元素,无法实现图片复制。

参考clipboard.js源码,了解了实现原理后(其实非常简单!:) ),我们就能自己动手封装一个复制方法:

概述 Range对象

Range表示包含节点和部分文本节点的文档片段。最常见的就是用户在浏览器拖动鼠标选择的内容(user selection)

比如上图这块蓝色高亮区域。

在现代浏览器中(IE9以上),你可以通过Document.createRange()方法或者new Range()创建一个Range对象;当需要获取user selection时,你应该使用window.getSelection()方法获取Selection对象

有点懵?

刚了解了Range对象,而Selection对象又是什么?阅读了文档之后,还是疑惑它们之间的区别?


Selection对象表示用户的选择,而Range对象则表示文档的连续部分,与任何视觉表示无关。一个Selection对象几乎可由0到多个Range表示出来,当然,Range对象也能独立于Selection而被完全的创建和修改。

简单的演示代码

html部分:

这是一段文字 AAAAAAAAAA BBBBBBBBBB Range

js部分:

var btn1 = document.getElementById("button1"),
    btn2 = document.getElementById("button2"),
    input = document.getElementById("input"),
    rangespan = document.getElementById("range");
    
var selection = window.getSelection(),
    range = document.createRange();
btn1.addEventListener("click", function(event) {
    input.value = selection.toString();
}); 
btn2.addEventListener("click", function(event) {
    range.selectNode(rangespan);
    selection.removeAllRanges(); //删除包含在selection原本的range,也就是取消用户选中的范围
    selection.addRange(range); //让选中部分变成我们自己定义的节点内容
}); 

演示地址:

https://jsfiddle.net/muvhqcnf...

一点就会 :)

兼容陈旧IE版本

Microsoft提供了类似的TextRange接口。
在实际代码部分会展示Microsoft TextRange的基本使用。

execCommand方法

execCommand方法允许运行命令来操纵可编辑区域的内容。该方法的第一个参数是命令的名称,参数类型为DOMString。
在这里,我们将利用execCommand方法的copy命令实现复制选中的内容:

document.execCommand("copy")

execCommand API起源于IE,后来被添加到HTML5(HTML Editing APIs),在各浏览器的表现会有不同。更多请查看文档。

我们回到前面的演示代码,将btn1的点击事件替换成execCommand命令:

btn1.addEventListener("click", function(event) {
    //input.value = selection.toString();
    document.execCommand("copy");
}); 

拖动鼠标选择文字,点击按钮后看看能粘贴出什么:)

复制图片功能的具体实现 封装可以兼容ie的getSelect方法

还记得前面的例子里,我们通过rangeselectNode(node)方法获取节点, 再使用selectionremoveAllRanges()方法和addRange(range)将节点替换我们获取的节点。在这里,我们同样可以这样选中我们目标的img节点:

const getSelect = targetNode => {
  if (window.getSelection) {
    //chrome等主流浏览器
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNode(targetNode);
    selection.removeAllRanges();
    selection.addRange(range);
  } else if (document.body.createTextRange) {
    //ie
    var range = document.body.createTextRange();
    range.moveToElementText(targetNode);
    range.select();
  }
}
派发事件

为了不浪费性能,我们使用事件委托到希望被复制的节点上。这里对传入的nodeName进行处理,方便自由的控制被复制一个或多个节点类型。默认为

const clipboardHandler = (nodeName, event) => {
  event = event || nodeName; //不传参时
  const type = Object.prototype.toString.call(nodeName).replace(/[objects|]/g, "");
  const target = event.target || event.srcElement;

  var result = false;
  switch (type) {
    case "String":
      result = (target.nodeName.toLowerCase() === nodeName);
      break;
    case "Array":
      result = nodeName.some(item => target.nodeName.toLowerCase() === item);
      break;
    case "Object":
      nodeName = null;
    default:
      result = (target.nodeName === "IMG");
  }

  if (result) {
    //调用之前封装好的getSelect方法
    getSelect(target);
    document.execCommand("copy");
  }
}

调用:

[element].addEventListener("mousedown", clipboardHandler); //预备拖动图片按下鼠标时执行复制

传递参数(字符串或数组):

var [somename]Handler = clipboardHandler.bind(null, [nodeName]);
[element].addEventListener([eventType],[somename]Handler);

完整代码演示地址:

已验证在chrome和ie8上可行(ie8需要对es6语法与bind和addEventListener方法进行pollyfill)

希望能够帮助到你:)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95425.html

相关文章

  • Web聊天工具的富文本输入框

    摘要:由于我们的富文本输入框比较简单,所以只需要处理两类数据即可,其一是普通的文本类型数据,包括表情其二则是图片类型数据。 最近折腾 Websocket,打算开发一个聊天室应用练练手。在应用开发的过程中发现可以插入 emoji ,粘贴图片的富文本输入框其实蕴含着许多有趣的知识,于是便打算记录下来和大家分享。 仓库地址:chat-input-box预览地址:https://codepen.io...

    iKcamp 评论0 收藏0
  • 前端er怎样操作剪切复制以及禁止复制+破解等

    摘要:取消默认的复制事件被复制的文字等下插入防知乎掘金复制一两个字则不添加版权信息超过一定长度的文字就添加版权信息作者链接来源掘金著作权归作者所有。以上参考资料高程操作剪贴板网页上如何实现禁止复制粘贴以及如何破解原生实现点击按钮复制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...

    mikasa 评论0 收藏0
  • 前端er怎样操作剪切复制以及禁止复制+破解等

    摘要:取消默认的复制事件被复制的文字等下插入防知乎掘金复制一两个字则不添加版权信息超过一定长度的文字就添加版权信息作者链接来源掘金著作权归作者所有。以上参考资料高程操作剪贴板网页上如何实现禁止复制粘贴以及如何破解原生实现点击按钮复制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...

    amuqiao 评论0 收藏0
  • 前端er怎样操作剪切复制以及禁止复制+破解等

    摘要:取消默认的复制事件被复制的文字等下插入防知乎掘金复制一两个字则不添加版权信息超过一定长度的文字就添加版权信息作者链接来源掘金著作权归作者所有。以上参考资料高程操作剪贴板网页上如何实现禁止复制粘贴以及如何破解原生实现点击按钮复制文本 showImg(https://segmentfault.com/img/remote/1460000015942602?w=1280&h=720); 前言...

    DevTalking 评论0 收藏0
  • document.execCommand()方法处理Html数据

    摘要:设定元素的属性为绝对。将当前选中区复制到剪贴板并删除之。插入隐藏控件覆盖当前选中区。减少选中区所在格式化块的缩进。传递整数将显示用户界面,整数将跳过它。方法受到的影响会闪烁。 document.execCommand()方法处理Html数据时常用语法格式如下:document.execCommand(sCommand[,交互方式, 动态参数]) 其中:sCommand为指令参数(如下例...

    Chaz 评论0 收藏0

发表评论

0条评论

MageekChiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<