使用钩子调整反应元素大小

问题描述 投票:0回答:1

我正在尝试创建一个允许我调整元素大小的钩子。我使用这个答案作为参考点并创建了以下内容。

调整大小可以,但不准确。调整大小手柄不跟随光标,并且会偶尔移动。

任何人都可以帮我理解这个钩子有什么问题吗?

代码笔

预览: enter image description here

挂钩:

interface Dimensions {
  width: number | null;
  height: number | null;
}

interface UseResizableProps {
  elementRef: React.RefObject<HTMLDivElement>;
  handleRef: React.RefObject<HTMLDivElement>;
}

function useResizable({ elementRef, handleRef }: UseResizableProps) {
  const dimensions = useRef<Dimensions>({ width: null, height: null });

  // Since we dont know the size that the element should initialize to,
  // we need to grab the sizes from the element rect
  useEffect(() => {
    if (elementRef.current) {
      const rect = elementRef.current.getBoundingClientRect();
      dimensions.current = { height: rect.height, width: rect.width };
    }
  }, [elementRef]);

  useEffect(() => {
    function handleMouseDownE(mouseDownEvent: MouseEvent) {
      const startPosition = {
        x: mouseDownEvent.pageX,
        y: mouseDownEvent.pageY,
      };
      function onMouseMove(mouseMoveEvent: MouseEvent) {
        if (
          dimensions.current.height === null ||
          dimensions.current.width === null
        ) {
          return;
        }
        dimensions.current = {
          width:
            dimensions.current.width - startPosition.x + mouseMoveEvent.pageX,
          height: dimensions.current.height,
        };

        if (
          elementRef?.current?.style.width !== undefined &&
          dimensions.current.width
        ) {
          const px = `${dimensions.current.width}px`;
          elementRef.current.style.width = px;
        }
      }
      function onMouseUp() {
        document.body.removeEventListener("mousemove", onMouseMove);
      }
      document.body?.addEventListener("mousemove", onMouseMove);
      document.body?.addEventListener("mouseup", onMouseUp, { once: true });
    }
    handleRef?.current?.addEventListener("mousedown", handleMouseDownE);
  });
}

挂钩用法:

function App() {
  const elementRef = useRef<HTMLDivElement>(null);
  const handleRef = useRef<HTMLDivElement>(null);

  useResizable({ elementRef, handleRef });

  return (
    <div className="App">
      <div className="resizable" ref={elementRef}>
        <div className="resize-handle" ref={handleRef}></div>
      </div>
    </div>
  );
}

款式:

.resizable {
  width: 500px;
  height: 500px;
  background-color: lightpink;
  position: relative;
}

.resize-handle {
  width: 5px;
  height: 100%;
  background-color: orangered;
  right: 0;
  position: absolute;
  cursor: e-resize;
}

reactjs react-hooks dom-events
1个回答
1
投票

问题在于宽度计算。您将 currentDimensions 称为 mouseDown 事件首次触发时的尺寸,然后在 mouseMouse 触发时修改它。 解决方案是在 mouseDown 事件触发时获取尺寸的副本,例如 来自:

    function handleMouseDownE(mouseDownEvent: MouseEvent) {
      const startPosition = {
        x: mouseDownEvent.pageX,
        y: mouseDownEvent.pageY,
      };
      function onMouseMove(mouseMoveEvent: MouseEvent) {
        if (
          dimensions.current.height === null ||
          dimensions.current.width === null
        ) {
          return;
        }
        dimensions.current = {
          width:
            dimensions.current.width - startPosition.x + mouseMoveEvent.pageX,
          height: dimensions.current.height,
        };

        if (
          elementRef?.current?.style.width !== undefined &&
          dimensions.current.width
        ) {
          const px = `${dimensions.current.width}px`;
          elementRef.current.style.width = px;
        }
      }

致:

    function handleMouseDownE(mouseDownEvent: MouseEvent) {
      const startDimensions = { ...dimensions.current }; // <<<< Add this
      const startPosition = {
        x: mouseDownEvent.pageX,
        y: mouseDownEvent.pageY,
      };
      function onMouseMove(mouseMoveEvent: MouseEvent) {
        if (
          dimensions.current.height === null ||
          dimensions.current.width === null
        ) {
          return;
        }
        dimensions.current = {
          width:
            startDimensions.width - startPosition.x + mouseMoveEvent.pageX, // <<<< Add this
          height: startDimensions.height,
        };

        if (
          elementRef?.current?.style.width !== undefined &&
          dimensions.current.width
        ) {
          const px = `${dimensions.current.width}px`;
          elementRef.current.style.width = px;
        }
      }
© www.soinside.com 2019 - 2024. All rights reserved.