我的 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>
);
};