js实现复制二维码

js实现复制二维码

1.介绍

项目中有一个二维码复制功能,首先是根据所选择的组织与邀请成为的角色,后端返回一个二维码数据链接,将二维码渲染展示在页面上;然后在点击复制按钮时可以复制二维码,在其它的地方可以直接粘贴使用。复制二维码还不是简单的复制二维码图片,而是还要加上一些其它的描述西信息,如邀请进行的项目、邀请到的组织、邀请成为的角色等,这些信息和二维码一起转成一个图片进行复制。

2.思路

思路一:document.execCommand。查文档发现已废弃,所以不考虑。

https://juejin.cn/post/6909237803050074126

思路二:开源库(clipboard.js)。经验证也不适合

1.这个库依赖的 document.execCommand API 已被废弃了 ;

2.这个库只支持文字的复制;(文字复制时推荐这个库);

思路三:Clipboard API 。可用,但是有一些限制。

3.Clipboard API实现复制

https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardItem

局限:由于新版浏览器的安全策略,clipboard只有在安全域名下才可以访问,http域名下会显示undefined,但使用https开头的域名,或localhost,就可以访问navigator.clipboard。所以使用此API必须是在https安全协议访问或localhost本地安全访问。

步骤

1.生成一个整体HTML元素,渲染在页面上同时不让用户看到。

这里这么做的原因是因为后续要使用dom-to-image将该元素转为blob数据,如果不渲染在页面上,最后复制出的图片是一个空白页;

这里还有一个坑,这个整体元素不能使用绝对定位,否则复制出的图片仍是一个空白页,不知道为什么。所以这里使用了相对定位,给相对定位加z-index进行不可见。

<div class="copy-content flex flex-col items-center" :style="`display:${copyclick?'flex':'none'}`">
      <div >请使用...扫码加入</div>
      <div>...项目</div>
      <div class="text">成为 ...</div>
      <img v-if="qrcode" :src="qrcode" >
      <div class="text text-base">该二维码7天(...)内有效</div>
</div>

<style>
   .copy-content {
      display: none;
      position: relative;
      z-index: -1;
	  ......
   }
</style>

2.使用dom-to-image转为blob数据。

<el-button@click="handleCopyImg">复制</el-button>
<a :href="blobToUrl(convertBase64ToBlob(qrcode.replace('data:image/png;base64,', ''), 'image/png'))" ref='qrcodeLink'>下载</a>

import domtoimage from 'dom-to-image';

handleCopyImg() {
  if (navigator.clipboard) {
    this.copyclick = true;
    setTimeout(async () => {
      try {
        const node = document.getElementsByClassName('copy-content')[0];
        // 方式一:这种方式也适合与base64格式的图片进行复制
        // const res = await domtoimage.toPng(node);
        // const blobInput = this.convertBase64ToBlob(res.replace('data:image/png;base64,', ''), 'image/png');
        // 方式二:一步到位
        const blobInput = await domtoimage.toBlob(node);
      } catch (err) {
        this.$message.error('复制二维码失败');
        this.copyclick = false;
      }
    });
  }
},
convertBase64ToBlob(base64, type) {
  const bytes = window.atob(base64);
  const ab = new ArrayBuffer(bytes.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], { type });
},
blobToUrl(blobData) {
  return URL.createObjectURL(blobData);
},

3.使用clipboard进行复制。

handleCopyImg() {
  if (navigator.clipboard) {
    this.copyclick = true;
    setTimeout(async () => {
      try {
        const node = document.getElementsByClassName('copy-content')[0];
        const blobInput = await domtoimage.toBlob(node);
        const clipboardItemInput = new ClipboardItem({ 'image/png': blobInput });
        await navigator.clipboard.write([clipboardItemInput]);
        this.$message.success('复制二维码成功');
        this.copyclick = false;
      } catch (err) {
        console.log('err');
        this.$message.error('复制二维码失败');
        this.copyclick = false;
      }
    });
  } else {
    this.$refs.qrcodeLink.click();
  }
},

4.扩展小demo

贴两个其他博客中的小demo,省的想看的时候再找了。

1.图片的复制与粘贴demo

局限: 粘贴图片除了可以粘贴网页中的图片,也可以粘贴微信、QQ等软件中的截图,但直接从硬盘中复制的图片(本地图片)不可以 。

<!doctype html>
<html lang="zn">
 <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <title>复制图片</title>
  <style>
	.container {
	  display: flex;
	}
	.block {
	  margin-right: 30px;
	}
	img {
	  width: 300px;
	  height: 225px;
	}
  </style>
 </head>
 <body>
    <div class="container">
      <div class="block">
        <button id="copyBtn">复制下图</button>
        <div>
          <img src="https://www.kkkk1000.com/images/clipboard/img/1.png" id="copyImg">
        </div>
      </div>
      <div class="block">
        <button id="pasteBtn">粘贴图片</button>
        <div>
          <img id="pasteImg">
        </div>
      </div>
    </div>
    <p>粘贴图片除了可以粘贴网页中的图片,也可以粘贴微信、QQ等软件中的截图,但直接从硬盘中复制的图片不可以。</p>
 <script>
      //复制图片
      var copyBtn = document.querySelector('#copyBtn')
      var copyImg = document.querySelector('#copyImg')
      copyBtn.addEventListener('click', () => {
        writeImg()
      })
      async function writeImg() {
        const imgURL = copyImg.src
        const data = await fetch(imgURL)
        const blob = await data.blob()
        await navigator.clipboard.write([
          new ClipboardItem({
            [blob.type]: blob
          })
        ])
		alert('已写入图片!')
      }
      //粘贴图片
      var pasteBtn = document.querySelector('#pasteBtn')
      var pasteImg = document.querySelector('#pasteImg')
      pasteBtn.addEventListener('click', () => {
        readImg()
      })
      function readImg() {
        //获取权限
        navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
          if (result.state == 'granted' || result.state == 'prompt') {
            //读取剪贴板
            navigator.clipboard.read()
              .then(data => {
                for (let i = 0; i < data.length; i++) {
                  if (!data[i].types.includes('image/png')) {
                    alert('请先复制图片!')
                  } else {
                    data[i].getType('image/png').then(blob => {
                      pasteImg.src = URL.createObjectURL(blob)
                    })
                  }
                }
              })
              .catch(err => {
                alert(err)
              })
          } else {
            alert('请允许读取剪贴板!')
          }
        })
      }
 </script>
 </body>
</html>

2.原生图片粘贴demo

<html>
	<head>
		<title>test chrome paste image</title>
		<style>
			#non-editable img{
				width: 300px;
			}
			#editable {
				margin-top: 20px;
				width: 400px;
				height: 300px;
				border: 1px dashed blue;
			}
			
			#editable img{
				width: 300px;
			}
		</style>
	</head>
	<body>
		<h2>在浏览器中测试图像粘贴</h2>
		<div id="non-editable">
			<p>复制下面的img,然后粘贴到下面的区域</p>
			<img
				src="https://www.kkkk1000.com/images/clipboard/img/1.png" />
		</div>
		<div id="editable" contenteditable="true">
			<p>这是一个可编辑的div区域</p>
			<p>将图像粘贴到这里。</p>
		</div>
	</body>
</html>
<script type="text/javascript">
	window.onload = function() {
		function paste_img(e) {
			if (e.clipboardData.items) {
				// google-chrome 
				ele = e.clipboardData.items
				for (var i = 0; i < ele.length; ++i) {
					if (ele[i].kind == 'file' && ele[i].type.indexOf('image/') !== -1) {
						var blob = ele[i].getAsFile();
						window.URL = window.URL || window.webkitURL;
						var blobUrl = window.URL.createObjectURL(blob);
						var new_img = document.createElement('img');
						new_img.setAttribute('src', blobUrl);
						var new_img_intro = document.createElement('p');
						new_img_intro.innerHTML =
							'粘贴的img url: <br /><a target="_blank" href="' + blobUrl +
							'">' + blobUrl + '</a>';
 
						document.getElementById('editable').appendChild(new_img);
						document.getElementById('editable').appendChild(new_img_intro);
					}
 
				}
			} else {
				alert('non-chrome');
			}
		}
		document.getElementById('editable').onpaste = function() {
			paste_img(event);
			return false;
		};
	}
</script>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值