useElementByPoint

useElementByPoint 是一個用於獲取指定坐標下的元素的 Hook。

useElementByPoint 封裝了 document.elementFromPoint()(或多元素模式下的 elementsFromPoint()),用於響應式查詢給定 x/y 座標處的 DOM 元素。它支援按間隔或透過 requestAnimationFrame 進行輪詢,並回傳一個可暫停的物件,包含匹配的元素、isSupported 旗標以及 pause/resume 控制項。

使用場景

  • 建構元素檢查工具或視覺偵錯器,用於高亮懸停的元素
  • 實作需要在特定座標偵測放置目標的自訂拖放邏輯
  • 建立識別游標下 UI 元素的互動式教學或導覽覆蓋層

注意事項

  • SSR 安全:在伺服器端渲染時回傳 isSupported: falsenull 元素。伺服器上不會存取 document
  • 效能:使用 interval 選項控制輪詢頻率。requestAnimationFrame 提供最流暢的更新,但 CPU 使用率較高。
  • 相關 hooks:搭配 useMouse 追蹤游標位置,以及 useElementBounding 獲取偵測到的元素尺寸。

Usage

Live Editor
function Demo() {
  const { clientX: x, clientY: y } = useMouse();
  const { element, pause, resume } = useElementByPoint({ x, y });
  const bounding = useElementBounding(element);

  useEventListener("scroll", bounding.update, null, { capture: true });
  const boxStyles = (() => {
    if (element) {
      return {
        display: "block",
        width: `${bounding.width}px`,
        height: `${bounding.height}px`,
        left: `${bounding.left}px`,
        top: `${bounding.top}px`,
        backgroundColor: "#3eaf7c44",
        transition: "all 0.05s linear",
        position: "fixed",
        pointerEvents: "none",
        zIndex: 9999,
        border: "1px solid var(--vp-c-brand)",
      };
    }
    return {
      display: "none",
    };
  })();
  const pointStyles = (() => ({
    transform: `translate(calc(${x}px - 50%), calc(${y}px - 50%))`,
    position: "fixed",
    top: 0,
    left: 0,
    pointerEvents: "none",
    width: "8px",
    height: "8px",
    borderRadius: "50%",
    backgroundColor: "#4ade80",
    boxShadow: "0 0 2px rgba(0,0,0,0.3)",
    zIndex: 999,
  }))();

  return (
    <>
      <div style={boxStyles} />
      <div style={pointStyles} />
      <div style={{ display: "flex", alignItems: "center" }}>
        <span style={{ marginRight: "16px" }}>X: {x}</span>
      </div>
      <div style={{ display: "flex", alignItems: "center" }}>
        <span style={{ marginRight: "16px" }}>Y: {y}</span>
      </div>
      <div>
        <button onClick={pause}>暫停</button>
        <button onClick={resume}>恢復</button>
      </div>
    </>
  );
}
render(<Demo />);
Result

API

UseElementByPoint

Returns

UseElementByPointReturn<M>

Arguments

參數名描述類型預設值
options配置项UseElementByPointOptions<M> (必填)-

UseElementByPointOptions

參數名描述類型預設值
x点的 x 坐标number | (() => number) (必填)-
y点的 y 坐标number | (() => number) (必填)-
document要查询的文档Document | null-
multiple是否查询多个元素M-
interval查询元素的间隔number | 'requestAnimationFrame'-
immediate是否立即查询元素boolean-

UseElementByPointReturn

參數名描述類型預設值
isSupported功能是否支持boolean (必填)-
element查询到的元素M extends true ? Element[] : Element | null (必填)-
isActive一个 ref,表示一个 pausable 实例是否处于激活状态boolean (必填)-
pause暂时暂停效果的执行Fn (必填)-
resume恢复效果Fn (必填)-

Fn

export type Fn = (this: any, ...args: any[]) => any;