当前位置: 首页 > news >正文

python 复制图片到剪贴板_JS实现将图片复制到剪贴板

前言

最近项目新增需求:用户能够拖拽页面上的图片文件到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()方法获取

有点懵?

刚了解了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); //让选中部分变成我们自己定义的节点内容

});

一点就会 :)

兼容陈旧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方法

还记得前面的例子里,我们通过range的selectNode(node)方法获取节点, 再使用selection的removeAllRanges()方法和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(/\[object\s|\]/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)

希望能够帮助到你:)

相关文章:

  • 马斯洛需求的五个层次_如何合理满足孩子需求?善用马斯洛需求层次理论,你也是聪明家长...
  • python调用api做用户登录认证_Python构建RESTful网络服务[Django篇:用户接入控制,认证与权限]...
  • pythonocc安装_PythonOCC开发-如何搭建开发环境和一个创建圆台例子
  • python怎么找到视频教程_哪里能找到 Python 视频教程地址?
  • mybatis嵌套子查询_InfluxDB常见问题和解答 - 如何在InfluxDB中实现嵌套子查询
  • select子查询返回 值_从零学会SQL:复杂查询,D4
  • python concat axis_Python NumPy中sum()函数详解 axis与keepdims图解
  • python echarts mysql_Django中从mysql数据库中获取数据传到echarts方式
  • skywalking原理_链路追踪 SkyWalking 源码分析——Collector Naming Server 命名服务
  • python print 调试_python 调试: print / assert / logging / pdb
  • 信息系统项目管理师论文_高级软考信息系统项目管理师考试技巧之论文摘要
  • imp oracle reschema_Oracle数据库逻辑备份之exp/imp(一)
  • aspnet是前端还是后端_谁能解释一下“前端开发”与“.NET”有什么区别和联系...
  • oracle rank 语法_Oracle用于排名的函数
  • extjs string类型转date_Extjs 时间格式的转换
  • Android系统模拟器绘制实现概述
  • Flex布局到底解决了什么问题
  • in typeof instanceof ===这些运算符有什么作用
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Java深入 - 深入理解Java集合
  • scala基础语法(二)
  • Spring Boot快速入门(一):Hello Spring Boot
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 给初学者:JavaScript 中数组操作注意点
  • 一、python与pycharm的安装
  • 以太坊客户端Geth命令参数详解
  • 云大使推广中的常见热门问题
  • ​香农与信息论三大定律
  • #FPGA(基础知识)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $ git push -u origin master 推送到远程库出错
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (2.2w字)前端单元测试之Jest详解篇
  • (c语言)strcpy函数用法
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (Matlab)使用竞争神经网络实现数据聚类
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)EOS中账户、钱包和密钥的关系
  • (转)http-server应用
  • (转)VC++中ondraw在什么时候调用的
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • (状压dp)uva 10817 Headmaster's Headache
  • .Net Core和.Net Standard直观理解
  • .Net Web项目创建比较不错的参考文章
  • .NET 发展历程
  • .Net 路由处理厉害了
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .Net中ListT 泛型转成DataTable、DataSet
  • .Net中间语言BeforeFieldInit