禁用时如何禁用 VictoryZoomContainer 的平移钩?

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

我的 VictoryZoomContainer 的平移功能与鼠标挂钩,即使我通过 React 状态禁用它也是如此。我在屏幕上拖动光标时禁用了平移功能,但是当我重新启用平移功能时,容器会快速回到我当前的鼠标位置。

我的目标是禁用平移功能,将我的鼠标拖过屏幕,然后在不移动平移域的情况下重新启用它。

我试图通过 VictoryZoomContainer 的

disable
道具禁用平移/缩放功能。对于鼠标被按下和移动的时间,它保持不动;但是当鼠标按钮被释放(鼠标弹起)时,平移域会捕捉到鼠标的当前位置并保持钩住鼠标的移动,直到我再次按下并释放。

处理整个“窗格”(我的应用程序的交互区域)和带有 VictoryZoomContainer 的 Victory 图表的相关 React 组件代码:

const pixelsToDomain = (
  pixels: number,
  minPixels: number,
  maxPixels: number,
  minDomain: number,
  maxDomain: number
) => {
  return (
    ((pixels - minPixels) / (maxPixels - minPixels)) * (maxDomain - minDomain) +
    minDomain
  );
};

const DigitalPane = (props: DigitalPaneProps) => {
  const [cursorIsHooked, setCursorIsHooked] = useState(false);
  const [cursorX, setCursorX] = useState(5);
  const [zoomDomain, setZoomDomain] = useState({ x: [0, 6], y: [0, 10] } as {
    x: DomainTuple;
    y: DomainTuple;
  });
  
  const [pointerIcon, setPointerIcon] = useState("default" as PointerIcon);

  const hookCursor = () => {
    setCursorIsHooked(true);
    console.log("cursor hooked");
  };

  const unhookCursor = () => {
    if (cursorIsHooked) {
      setCursorIsHooked(false);
      console.log("cursor unhooked");
    }
  };

  const handleZoomDomainChange = (domain: {
    x: DomainTuple;
    y: DomainTuple;
  }) => {
    if (cursorIsHooked) {
      return;
    }
    setZoomDomain(domain);
  };

  const handleMouseMove = (e: MouseEvent) => {
    if (!cursorIsHooked) {
      return;
    }

    const paneWidthPixels = width;
    const graphXMinPixels = leftPadding;
    const graphXMaxPixels = paneWidthPixels - rightPadding;
    const mousePixelsOffsetX = e.nativeEvent.offsetX;

    // remember, x and y are flipped because it's a horizontal chart
    const graphXMin: number = zoomDomain.y[0] as number;
    const graphXMax: number = zoomDomain.y[1] as number;

    const x = pixelsToDomain(
      mousePixelsOffsetX,
      graphXMinPixels,
      graphXMaxPixels,
      graphXMin,
      graphXMax
    );

    setCursorX(x);
  };

  return (
    <PaneWrapper
      $isDark={isDarkTheme(blueprintTheme)}
      ref={observe}
      onMouseMove={handleMouseMove}
      onMouseLeave={() => {
        unhookCursor();
      }}
      onMouseDown={(e: MouseEvent) => {
        console.log("MOUSE DOWN");

        // get the mouse's relative domain (x coordinate) by converting the mouse's x pixel offset to a domain value
        const relativeDomain = pixelsToDomain(
          e.nativeEvent.offsetX,
          leftPadding,
          width - rightPadding,
          zoomDomain.y[0] as number,
          zoomDomain.y[1] as number
        );

        // if the mouse's relative domain is nearby the cursor, hook the cursor
        if (Math.abs(relativeDomain - cursorX) < 0.08) {
          hookCursor();
          return;
        }
      }}
      onMouseUp={() => {
        console.log("MOUSE UP");
        unhookCursor();
      }}
    >
      <VictoryChart
        width={width}
        height={height}
        padding={{
          top: 15,
          bottom: 33,
          left: leftPadding,
          right: rightPadding,
        }}
        horizontal
        domainPadding={{
          x: 200,
          y: 0,
        }}
        minDomain={{ y: 0 }}
        maxDomain={{ y: 10, x: 6 }}
        groupComponent={<CanvasGroup />}
        containerComponent={
          <VictoryZoomContainer
            disable={cursorIsHooked}
            onZoomDomainChange={(domain) =>
              handleZoomDomainChange(
                domain as { x: DomainTuple; y: DomainTuple }
              )
            }
            responsive={true}
          />
        }
      >
        <VictoryBar
          groupComponent={<CanvasGroup />}
          style={{
            data: {
              fill: "gray",
            },
          }}
          data={[
            { x: 1, y0: 3, y: 8 },
            { x: 2, y0: 4, y: 10 },
            { x: 3, y0: 2, y: 8 },
            { x: 4, y0: 1, y: 6 },
            { x: 5, y0: 2, y: 8 },
          ]}
        />
        <VictoryLine
          groupComponent={<CanvasGroup />}
          y={() => cursorX}
          style={{
            data: {
              stroke: "red",
              strokeWidth: 8,
              cursor: pointerIcon,
            },
          }}
          events={[
            {
              target: "data",
              eventHandlers: {
                onMouseEnter: () => {
                  setPointerIcon("ew-resize");
                },
                onMouseLeave: () => {
                  setPointerIcon("default");
                },
              },
            },
          ]}
        />
      </VictoryChart>
    </PaneWrapper>
  );
};

视频示例: https://i.imgur.com/05Nnoab.mp4

reactjs react-hooks zooming victory-charts panning
© www.soinside.com 2019 - 2024. All rights reserved.