import { HTMLEditor } from '../lib' import { useEffect, useRef, useState } from 'react' export const useToolPostion = (editor: HTMLEditor | null, isDoc: boolean) => { const [position, setPosition] = useState<{ left: number; top: number, bottom: number, right: number, width: number, height: number } | null>(null) // 标识是否从编辑器内开始选择 const isSelectingRef = useRef(false) const updatePositionFromSelection = () => { if (!editor) { return } const view = editor.getDoc().view if (!view) { return } const selection = view.getSelection() if (!selection) return // 如果选区为空,不需要更新 const hasSelectAnything = selection.rangeCount === 0 || selection.toString().trim() === '' if (selection.isCollapsed || selection.rangeCount === 0 || hasSelectAnything) { setPosition(null) return } // 获取选区的 Range 对象 const range = selection.getRangeAt(0); // 获取选区末尾的位置 // 创建一个新的 Range,只包含选区的末尾点 const endRange = range.cloneRange(); endRange.collapse(false); // false 表示折叠到末尾 const rect = endRange.getBoundingClientRect(); const { top, left, bottom, right, width, height } = rect setPosition({ top, left, bottom, right, width, height }) } useEffect(() => { if (!editor || !isDoc) { return } const dom = editor.getDoc().document if (!dom) { return } const onMouseDown = () => { isSelectingRef.current = true } const onMouseUp = () => { // 只有从编辑器内开始选择时才处理 if (!isSelectingRef.current) { return } isSelectingRef.current = false setTimeout(() => { updatePositionFromSelection() }, 50) } const onScrollOrResize = () => { updatePositionFromSelection() } dom.addEventListener('mousedown', onMouseDown) dom.addEventListener('mouseup', onMouseUp) dom.addEventListener('scroll', onScrollOrResize) window.addEventListener('scroll', onScrollOrResize, true) window.addEventListener('resize', onScrollOrResize) return () => { dom.removeEventListener('mousedown', onMouseDown) dom.removeEventListener('mouseup', onMouseUp) dom.removeEventListener('scroll', onScrollOrResize) window.removeEventListener('scroll', onScrollOrResize, true) window.removeEventListener('resize', onScrollOrResize) } }, [editor, updatePositionFromSelection, isDoc]) return position }