react 复制内容到剪切板[超详细]

实现效果如下:

 ​​​​​​​

 实现思路与步骤:

 一.拿到选中的文本

二.设置复制图标的位置

三.将拿到的文本内容赋值给剪贴版

四.控制图标的显示状态

详细步骤:

 一.拿到选中的文本

const onGetSelectText = () => {
    return document.getSelection().toString();
  };

二.设置复制图标的位置

  1.拿到鼠标当前操作位置

     a.选中文本时,首先得鼠标双击屏幕选中,或者是shift+单击,然后释放鼠标,文本被选中,所以在这里我们使用onmouseup 事件

    document.addEventListener('mouseup', handleMouseup);

    b.通过事件监听,在handleMouseup=(e)=>{}中拿到当前鼠标相对于屏幕的位置 e.clientX,e.clientY。

 c.clientX,clientY获取当前鼠标位置

const handleMouseup = (el) => {
      let txt = onGetSelectText();
      if (txt) {
        setCopyText(txt);
        copyIConRef.current.style.left = el?.clientX;
        copyIConRef.current.style.top = el?.clientY + 12;
      }
    
    };

   计算好图标的位置后,通过定位来控制图标的显示位置,相对于滚动页面进行绝对定位

.SelectTextCopy {
  position: fixed;
  visibility: hidden;
  background: #d6dce6;
  padding: 4px;
  width: 28px;
  height: 28px;
  border-radius: 4px;
  border: 1px solid rgba(34, 47, 64, 0.06);
  box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.12);
  cursor: pointer;
}

三.点击copy图标,将拿到的文本内容传递给剪贴板

 <IcCopy
      ref={copyIConRef}
      className={'SelectTextCopy'}
      style={{ visibility: copyText ? 'visible' : 'hidden' }}
      onMouseDown={(e) => {
        e.stopPropagation();
     
      }}
      onClick={(e) => {
        //将拿到的文本赋值给剪贴板
        copyToClipboard(copyText);
        //这就是一个复制成功的提示框,可以自己写一个替代
        message.info('已复制');
        setCopyText('');
      }}
    />
 copyToClipboard(str: string) {
    return navigator?.clipboard?.writeText(str).catch((err) => {
      const el = document.createElement('textarea');
      el.value = str;
      document.body.appendChild(el);
      el.select();
      document.execCommand('copy');
      document.body.removeChild(el);
    });
  },

四.控制图标的显示状态

完成文本复制 以及文本取消选中状态时需要隐藏图标

 const handleMouseDown = (e) => {
      if (!e.shiftKey) {
         //鼠标单击时触发,但不包括同时按住shift键盘
        setCopyText('');
        window.getSelection().removeAllRanges();
      }
    };

 由于IcCopy 的onClick 与上述单击事件相互影响,所以在 IcCopy上加上onMouseDown ,阻止冒泡行为

 onMouseDown={(e) => {
        e.stopPropagation();
      }}

完整代码:AISelectTextCopy  组件

import { useEffect, useState, useRef } from 'react';
import IcCopy from '@/assets/workspace/Copy.svg';
import './index.scss';
import { message } from 'antd';

export default function SelectTextCopy() {
  const [copyText, setCopyText] = useState('');
  const copyIConRef = useRef(null);

  useEffect(() => {
    const onGetSelectText = () => {
      return document.getSelection().toString();
    };
    const handleMouseDown = (e) => {
      //鼠标单击时触发,但不包括同时按住shift键盘
      window.getSelection().removeAllRanges();
    };
    const handleMouseup = (el) => {
      let txt = onGetSelectText();
      if (txt) {
        setCopyText(txt);
        copyIConRef.current.style.left = el?.clientX;
        copyIConRef.current.style.top = el?.clientY + 12;
      }
   
    };

    document.addEventListener('mouseup', handleMouseup);
    document.addEventListener('mousedown', handleMouseDown);
    return () => {
      document.removeEventListener('mouseup', handleMouseup);
      document.removeEventListener('mousedown', handleMouseDown);
    };
  }, []);

  const copyToClipboard = (str: string) => {
    return navigator?.clipboard?.writeText(str).catch((err) => {
      const el = document.createElement('textarea');
      el.value = str;
      document.body.appendChild(el);
      el.select();
      document.execCommand('copy');
      document.body.removeChild(el);
    });
  };

  return (
    <IcCopy
      ref={copyIConRef}
      className={'SelectTextCopy'}
      style={{ visibility: copyText ? 'visible' : 'hidden' }}
      onMouseDown={(e) => {
        e.stopPropagation();
     
      }}
      onClick={(e) => {
        //将拿到的文本赋值给剪贴板
        copyToClipboard(copyText);
        //这就是一个复制成功的提示框,可以自己写一个替代
        message.info('已复制');
        setCopyText('');
      }}
    />
  );
}

copyToClipboard 复制文本方法

  copyToClipboard(str: string) {
    return navigator?.clipboard?.writeText(str).catch((err) => {
      const el = document.createElement('textarea');
      el.value = str;
      document.body.appendChild(el);
      el.select();
      document.execCommand('copy');
      document.body.removeChild(el);
    });
  },

AISelectTextCopy.less

.SelectTextCopy {
  position: fixed;
  visibility: hidden;
  background: #d6dce6;
  padding: 4px;
  width: 28px;
  height: 28px;
  border-radius: 4px;
  border: 1px solid rgba(34, 47, 64, 0.06);
  box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.12);
  cursor: pointer;
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值