UNPKG

ahooks

Version:
85 lines (84 loc) 2.67 kB
import { useRef, useState } from 'react'; import { getTargetElement } from '../utils/domTarget'; import useEffectWithTarget from '../utils/useEffectWithTarget'; const initRect = { top: NaN, left: NaN, bottom: NaN, right: NaN, height: NaN, width: NaN, }; const initState = Object.assign({ text: '' }, initRect); function getRectFromSelection(selection) { if (!selection) { return initRect; } if (selection.rangeCount < 1) { return initRect; } const range = selection.getRangeAt(0); const { height, width, top, left, right, bottom } = range.getBoundingClientRect(); return { height, width, top, left, right, bottom, }; } function useTextSelection(target) { const [state, setState] = useState(initState); const stateRef = useRef(state); const isInRangeRef = useRef(false); stateRef.current = state; useEffectWithTarget(() => { const el = getTargetElement(target, document); if (!el) { return; } const mouseupHandler = () => { let selObj = null; let text = ''; let rect = initRect; if (!window.getSelection) { return; } selObj = window.getSelection(); text = selObj ? selObj.toString() : ''; if (text && isInRangeRef.current) { rect = getRectFromSelection(selObj); setState(Object.assign(Object.assign(Object.assign({}, state), { text }), rect)); } }; // 任意点击都需要清空之前的 range const mousedownHandler = (e) => { // 如果是鼠标右键需要跳过 这样选中的数据就不会被清空 if (e.button === 2) { return; } if (!window.getSelection) { return; } if (stateRef.current.text) { setState(Object.assign({}, initState)); } isInRangeRef.current = false; const selObj = window.getSelection(); if (!selObj) { return; } selObj.removeAllRanges(); isInRangeRef.current = el.contains(e.target); }; el.addEventListener('mouseup', mouseupHandler); document.addEventListener('mousedown', mousedownHandler); return () => { el.removeEventListener('mouseup', mouseupHandler); document.removeEventListener('mousedown', mousedownHandler); }; }, [], target); return state; } export default useTextSelection;