您的位置:首页 > 移动开发

JS一键复制 兼容PC(包括图片)+移动端

2017-08-27 16:59 956 查看

一 兼容性

兼容PC+手机端,Chrome 42+、Edge 12+、Firefox 41+、IE、Opera 29+、Safari 10+,PC支持复制图片,手机端友好交互。其中:

- clipboard.js


- window.clipboardData 兼容IE

- 友好型补充(主要针对移动端)

二 整体思路

最近做了一个需要 一键复制 功能的网站,也是经历了一番挣扎,下面给出自己的一些总结,欢迎大家补充。

ZeroClipboard.js虽然兼容性较好,但需要Flash,本文不考虑。如不在意flash可以尝试

本文主体clipboard.js

针对不兼容的IE版本尝试使用window.clipboardData

交互友好型补充方案(主要针对移动端)

三 clipboard.js使用

官方文档:https://clipboardjs.com/#example-text

使用总结:

通过npm或者cdn或者直接 引入 clipboard.js

使用方法@1 行内

<!-- 复制内容节点 -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">

<!-- 触发节点 -->
<button class="btn" data-clipboard-action="copy" data-clipboard-target="#foo" data-clipboard-text="我是复制的内容,和前一个属性选其一使用">
<img src="assets/clippy.svg" alt="Copy to clipboard">
</button>

<script>
// 通过选择触发节点实例化复制
b7b9
/剪切功能(必须)
var clipboard = new Clipboard('.btn');

// 复制成功or失败后的回调函数,可以弹窗(toast)提示(可选)
clipboard.on('success', function(e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);

e.clearSelection();
});
clipboard.on('error', function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
</script>


其中

复制内容节点 可以是任何的html标签,只要有id或者class标识,但 cut (剪切)只支持input或textarea

data-clipboard-action copy(复制) 或 cut(剪切),默认copy

data-clipboard-target 目标节点(复制/剪切的内容)

data-clipboard-text 直接定义复制内容,这个和 data-clipboard-target 选其一使用即可(至于同时使用时哪个生效有兴趣的可以研究),这个可以应付多节点复制,当然下面还有其他方案。

3.使用方法@2 function

new Clipboard('.btn', {
target: function(trigger) {
return trigger.nextElementSibling; // 目标内容为出发节点的下一个节点
// return trigger.previousElementSibling; // 前一个节点
// return trigger.parentElement; // 父节点
// return document.getElementById('id'); // 直接    }
});

new Clipboard('.btn', {
text: function(trigger) {
return trigger.getAttribute('aria-label');
// return trigger.nextElementSibling.innerText;
// return document.getElementById('id').innerText;
}
});

new Clipboard('.btn', {
container: document.getElementById('modal')
});


这种是实例化的时候添加复制目标,添加目标方式有:

target return的是目标节点,当然return之前还可以执行一些其他事件,参数trigger一般是触发节点。这个方法可以支持复制图片

text return的是目标内容,不过这里貌似只支持原生JS的方法(innerText/value),我用jQuery的提示无效

container 这个我没用过,理解应该是返回复制内容的盒子节点,那就跟target类似了。官方解释是:

For use in Bootstrap Modals or with any other library that changes the

focus you’ll want to set the focused element as the container value.

4.clipboard.js的一些其他方法:

Clipboard.isSupported(),返回 true/false 可以用于提前检测是否支持clipboard.js

4.针对clipboard.js不支持的IE浏览器

那就是IE8及以下了,因为IE有个clipboardData方法,所以需要兼容的话可以解决,使用这个方法操作的时候会有弹窗提示用户是否允许访问剪贴板

首先是判断何时使用这个,第一反应是获取浏览器种类,想来其实是不用的,看代码

if (Clipboard.isSupported()) {
// 使用clipboard.js处理
}else if(window.clipboardData){
var btn = document.getElementById('btn'); // 触发节点
var copyText = document.getElementById('btn').innerText // 或value,要复制的内容
btn.onclick = function(){
window.clipboardData.setData('Text', copyText);
}
}else{
alert('您目前的浏览器不支持一键复制,请手动复制使用其他浏览器试试')
}


关于clipboardData,它有3个方法:

clearData(dataFormat) 删除剪贴板中指定格式的数据dataFormat:”text”,”url”

getData(dataFormat) 从剪贴板获取指定格式的数据。 dataFormat:”text”,”url”

setData(dataFormat, data) 给剪贴板赋予指定格式的数据。返回 true 表示操作成功。dataFormat:”text”,”url”,”file”,”html”,”image”;data: 剪贴数据

5. 针对不支持一键复制的友好性设置

当然这部分主要是手机端了,主要是让其更好的完成手动长按复制,那IOS好像有些地方长按并不会有反应(出现复制、全选等)。这种情况一般出现在非input/textarea(个人感觉clipboard.js对input的支持更好一些,但input内容不能换行…textarea移动端有时候会有问题)标签下,比如div,那怎样让其支持呢?

<div contenteditable="true" onkeydown="return false;" onpaste="return false;">
内容1<br>
内容2
</div>


contenteditable属性可以让盒子内容处于可以编辑状态,我们只要这个状态,而不是让用户真的能编辑
onkeydown="return false;" onpaste="return false;"
禁用键盘和右键粘贴

针对IOS的Safari 10以下或者不支持clipboard.js的环境,有更好的用户体验方案,那就是用户点一下复制内容就自动帮其全部选中,这样用户只需点击复制

针对div contenteditable:

document.addEventListener('selectionchange', function(){
var t = window.getSelection().anchorNode;
var tParent = t.parentNode.id == 'mobileCopyText'; //className亦可
if (t && tParent && t.parentNode.innerText != window.getSelection()) {
window.getSelection().selectAllChildren(tParentNode)
}
})


简单解释一下原理:就是给 选区内容改变(selectionchange)(光标位置也会触发)添加一个监听事件,一旦触发,当(if条件)

选取内容开始位置(t)存在(为真)

其节点为复制内容的节点

选中的区域并不是需要复制内容的全部

这个时候选中 复制内容的父节点(有时候你可能需要parentNode两次)下的所有内容

关于getSelection()感兴趣的可以自己了解更多

针对input:

$('input').focus(function(){
$(this).select()
})


可能有人会问这么好的事情为什么说是只针对IOS,原因是测试发现Android下有些怪异的现象,那就是通过这种方法全选中后你点复制,但事实上你并没有复制到内容(尴尬)可能是个别浏览器的锅。所以最好还是判断一下IOS再用吧,怎么判断这里就不说了。另外手机端如何复制到图片还没有方案。

以上是我的总结,欢迎交流补充

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: