实现效果如下:
实现思路与步骤:
一.拿到选中的文本
二.设置复制图标的位置
三.将拿到的文本内容赋值给剪贴版
四.控制图标的显示状态
详细步骤:
一.拿到选中的文本
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;
}