chore(interactive-minimap): cleanup

This commit is contained in:
moklick
2022-11-01 16:10:23 +01:00
parent bd569ba3c1
commit b4658d4676
3 changed files with 26 additions and 31 deletions
@@ -1,4 +1,4 @@
import { MouseEvent } from 'react'; import { MouseEvent, useCallback } from 'react';
import ReactFlow, { import ReactFlow, {
Background, Background,
BackgroundVariant, BackgroundVariant,
@@ -7,6 +7,7 @@ import ReactFlow, {
Node, Node,
Edge, Edge,
useReactFlow, useReactFlow,
XYPosition,
} from 'reactflow'; } from 'reactflow';
import { MiniMap } from '@reactflow/interactive-minimap'; import { MiniMap } from '@reactflow/interactive-minimap';
@@ -113,6 +114,10 @@ const BasicFlow = () => {
); );
}; };
const onMiniMapClick = useCallback((event: MouseEvent, pos: XYPosition) => {
console.log(pos);
}, []);
return ( return (
<ReactFlow <ReactFlow
defaultNodes={initialNodes} defaultNodes={initialNodes}
@@ -128,7 +133,7 @@ const BasicFlow = () => {
fitView fitView
> >
<Background variant={BackgroundVariant.Dots} /> <Background variant={BackgroundVariant.Dots} />
<MiniMap /> <MiniMap onClick={onMiniMapClick} />
<Controls /> <Controls />
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}> <div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
+14 -25
View File
@@ -1,19 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { memo, MouseEvent, useEffect, useRef } from 'react'; import { memo, useEffect, useRef, MouseEvent } from 'react';
import cc from 'classcat'; import cc from 'classcat';
import shallow from 'zustand/shallow'; import shallow from 'zustand/shallow';
import { zoom, D3ZoomEvent, zoomIdentity } from 'd3-zoom'; import { zoom, D3ZoomEvent, zoomIdentity } from 'd3-zoom';
import { select, pointer } from 'd3-selection'; import { select, pointer } from 'd3-selection';
import {
useStore, import { useStore, getRectOfNodes, ReactFlowState, Rect, Panel, getBoundsOfRects, useStoreApi } from '@reactflow/core';
getRectOfNodes,
ReactFlowState,
Rect,
Panel,
getBoundsOfRects,
useStoreApi,
useReactFlow,
} from '@reactflow/core';
import MiniMapNode from './MiniMapNode'; import MiniMapNode from './MiniMapNode';
import { MiniMapProps, GetMiniMapNodeAttribute } from './types'; import { MiniMapProps, GetMiniMapNodeAttribute } from './types';
@@ -56,6 +48,7 @@ function MiniMap({
nodeStrokeWidth = 2, nodeStrokeWidth = 2,
maskColor = 'rgb(200, 200, 200, 0.9)', maskColor = 'rgb(200, 200, 200, 0.9)',
position = 'bottom-right', position = 'bottom-right',
onClick,
}: MiniMapProps) { }: MiniMapProps) {
const store = useStoreApi(); const store = useStoreApi();
const svg = useRef<SVGSVGElement>(null); const svg = useRef<SVGSVGElement>(null);
@@ -77,16 +70,13 @@ function MiniMap({
const height = viewHeight + offset * 2; const height = viewHeight + offset * 2;
const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision'; const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision';
const labelledBy = `${ARIA_LABEL_KEY}-${rfId}`; const labelledBy = `${ARIA_LABEL_KEY}-${rfId}`;
const { setCenter, setViewport, project } = useReactFlow();
const startTransform = useRef<[number, number]>([0, 0]);
const viewScaleRef = useRef(0); const viewScaleRef = useRef(0);
viewScaleRef.current = Math.max(w / elementWidth, h / elementHeight); viewScaleRef.current = Math.max(w / elementWidth, h / elementHeight);
const onClick = (event: MouseEvent) => { const onSvgClick = (event: MouseEvent) => {
const rfCoord = pointer(event); const rfCoord = pointer(event);
onClick?.(event, { x: rfCoord[0], y: rfCoord[1] });
console.log(rfCoord);
}; };
useEffect(() => { useEffect(() => {
@@ -94,11 +84,6 @@ function MiniMap({
const selection = select(svg.current as Element); const selection = select(svg.current as Element);
const zoomHandler = zoom() const zoomHandler = zoom()
.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
const rfCoord = pointer(event);
startTransform.current = rfCoord;
})
.on('zoom.wheel', (event: D3ZoomEvent<HTMLDivElement, any>) => { .on('zoom.wheel', (event: D3ZoomEvent<HTMLDivElement, any>) => {
const { transform, d3Selection, d3Zoom } = store.getState(); const { transform, d3Selection, d3Zoom } = store.getState();
@@ -112,25 +97,29 @@ function MiniMap({
10; 10;
const zoom = transform[2] * Math.pow(2, pinchDelta); const zoom = transform[2] * Math.pow(2, pinchDelta);
d3Zoom.scaleTo(d3Selection, zoom, startTransform.current); d3Zoom.scaleTo(d3Selection, zoom);
}) })
.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => { .on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
const { transform, d3Selection, d3Zoom } = store.getState(); const { transform, d3Selection, d3Zoom } = store.getState();
if (event.sourceEvent.type !== 'mousemove' || !d3Selection || !d3Zoom) { if (event.sourceEvent.type !== 'mousemove' || !d3Selection || !d3Zoom) {
return; return;
} }
let nextTransform = null;
const position = { const position = {
x: transform[0] - event.sourceEvent.movementX * viewScaleRef.current * transform[2], x: transform[0] - event.sourceEvent.movementX * viewScaleRef.current * transform[2],
y: transform[1] - event.sourceEvent.movementY * viewScaleRef.current * transform[2], y: transform[1] - event.sourceEvent.movementY * viewScaleRef.current * transform[2],
}; };
const nextTransform = zoomIdentity.translate(position.x, position.y).scale(transform[2]); nextTransform = zoomIdentity.translate(position.x, position.y).scale(transform[2]);
d3Zoom.transform(d3Selection, nextTransform); d3Zoom.transform(d3Selection, nextTransform);
}); });
selection.call(zoomHandler); selection.call(zoomHandler);
} }
}, [setCenter, setViewport, project]); }, []);
return ( return (
<Panel position={position} style={style} className={cc(['react-flow__minimap', className])}> <Panel position={position} style={style} className={cc(['react-flow__minimap', className])}>
@@ -141,7 +130,7 @@ function MiniMap({
role="img" role="img"
aria-labelledby={labelledBy} aria-labelledby={labelledBy}
ref={svg} ref={svg}
onClick={onClick} onClick={onSvgClick}
> >
<title id={labelledBy}>React Flow mini map</title> <title id={labelledBy}>React Flow mini map</title>
{nodes.map((node) => { {nodes.map((node) => {
+5 -4
View File
@@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { HTMLAttributes } from 'react'; import { HTMLAttributes, MouseEvent } from 'react';
import { Node, PanelPosition } from '@reactflow/core'; import { Node, PanelPosition, XYPosition } from '@reactflow/core';
export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string; export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string;
export interface MiniMapProps<NodeData = any> extends HTMLAttributes<SVGSVGElement> { export type MiniMapProps<NodeData = any> = Omit<HTMLAttributes<SVGSVGElement>, 'onClick'> & {
nodeColor?: string | GetMiniMapNodeAttribute<NodeData>; nodeColor?: string | GetMiniMapNodeAttribute<NodeData>;
nodeStrokeColor?: string | GetMiniMapNodeAttribute<NodeData>; nodeStrokeColor?: string | GetMiniMapNodeAttribute<NodeData>;
nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>; nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>;
@@ -12,4 +12,5 @@ export interface MiniMapProps<NodeData = any> extends HTMLAttributes<SVGSVGEleme
nodeStrokeWidth?: number; nodeStrokeWidth?: number;
maskColor?: string; maskColor?: string;
position?: PanelPosition; position?: PanelPosition;
} onClick?: (event: MouseEvent, position: XYPosition) => void;
};