PC端react实现一键复制图片功能

2,055 阅读2分钟

PC端react实现一键复制图片功能

背景:要求前端实现生成二维码并实现一键复制图片,

粘贴的效果图如下:

1.jpeg

本文用到的工具库: qrcode.react、b64-to-blob、html2canvas

首先将后端链接通过qrcode.react通过canvas生成二维码

               <div>
                <QRCode
                    value={'https://www.toutiao.com/a7003614188446761479/?log_from=105dea9e42726_1630663662691'}
                    size={200}
                    fgColor="#000000"
                  />
                </div>

然后再将整个dom转成canvas,此时会发现之前二维码已经是canvas了,不能再用canvas转了,所以我们修改下逻辑

 const [url, setUrl] = useState('');
  const qrCoderef = useRef();
  
 // 初始化,将canvas生成的二维码通过base64给到img标签
  const init = () => {
    const image = new Image();
    // 解决canvas跨域问题
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = ‘图片地址’;
    // 利用图片加载,触发事件
    image.onload = function () {
      try {
        const canvas = document.getElementsByTagName('canvas');
        const ctx = canvas[0].getContext('2d');
        ctx.drawImage(image, 200, 200);
        const imgUrl = canvas[0].toDataURL('image/png');
        setUrl(imgUrl);
      } catch {
        message.error('生成失败,请重试');
        props.onCancel();
      }
    };
  };

  useEffect(() => {
    init();
  }, []);

               <div ref={qrCoderef}>
                {!url&&<QRCode
                    value={'https://www.toutiao.com/a7003614188446761479/?log_from=105dea9e42726_1630663662691'}
                    size={200}
                    fgColor="#000000"
                  />}
                  {url && <div className={styles.imgDiv}>
                  <img className={styles.copyImg} src={url} alt="" />
                </div>}
               </div>

这样再通过html2canvas,就可以获取完整的dom节点,再通过b64-to-blob,将base64格式转换成blob,将blob赋值到浏览器剪切板就大功告成了。 具体操作:

 const copy = () => {
    html2canvas(qrCoderef.current, {
      useCORS: true
    }).then((canvas) => {
      const imgUrl = canvas.toDataURL('image/png');
      const str = imgUrl.replace(/data:image\/png;base64,/, '');
      const file = b64toBlob(str, 'image/png');
      const clipboardItemInput = new window.ClipboardItem({ 'image/png': file });
      window.navigator.clipboard.write([clipboardItemInput]);
    });
  };

完整代码:

import React, { useState, useEffect, useRef } from 'react';
import { Modal, message, Popover } from 'antd';
import QRCode from 'qrcode.react';
import html2canvas from 'html2canvas';
import b64toBlob from 'b64-to-blob';
import bg from 'public/1.png';


const QrCodeModal = (props) => {
  const [url, setUrl] = useState('');
  const qrCoderef = useRef();


  const copy = () => {
    html2canvas(qrCoderef.current, {
      useCORS: true
    }).then((canvas) => {
      const imgUrl = canvas.toDataURL('image/png');
      const str = imgUrl.replace(/data:image\/png;base64,/, '');
      const file = b64toBlob(str, 'image/png');
     
      const clipboardItemInput = new window.ClipboardItem({ 'image/png': file });
       //window.navigator.clipboard谷歌中在安全网络下才能访问,https/localhost,http是访问不到的
      window.navigator.clipboard.write([clipboardItemInput]);
    });
  };
  const init = () => {
    const image = new Image();
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = bg;
    image.onload = function () {
      try {
        const canvas = document.getElementsByTagName('canvas');
        const ctx = canvas[0].getContext('2d');
        ctx.drawImage(image, 200, 200);
        const imgUrl = canvas[0].toDataURL('image/png');
        setUrl(imgUrl);
      } catch {
        // 可能在canvas还没画完就调用造成失败
        message.error('生成失败,请重试');
        props.onCancel();
      }
    };
  };

  useEffect(() => {
    init();
  }, []);
  return (
    <Modal {...props} >
      <Popover content={<div><a onClick={() => copy()}>一键复制</a></div>} title="">
        <div ref={qrCoderef}>
          <h3 >你来啦?</h3>
          <p>
            <span>xxxx</span>
            <span>xxxxxxxxxxxxxx</span>
          </p>
          <div>
            {!url && <div >
              <QRCode
                value={'https://www.toutiao.com/a7003614188446761479/?log_from=105dea9e42726_1630663662691'}
                size={200}
                fgColor="#000000"
              />
            </div>}
            {url && <div >
              <img src={url} alt="" />
            </div>}
          </div>
        </div>
      </Popover>
    </Modal >
  );
};
export default QrCodeModal;