I want to achieve minimap functionality where in a Box or Div i’ll be rendering multiple react-d3-tree.
How can I achieve in react-d3-tree?
import React, { useRef, useState } from 'react';
import { Box } from '@mui/material';
import { Tree } from 'react-d3-tree';
import { data } from './data/TransactionForD3Tree';
const rawData = [data];
const groupByType = (node) => {
if (!node.children || node.children.length === 0) {
return node;
}
const groupedChildren = node.children.reduce((acc, child) => {
if (!acc[child.type]) {
acc[child.type] = { name: child.type, type: child.type, children: [] };
}
acc[child.type].children.push(groupByType(child));
return acc;
}, {});
return {
...node,
children: Object.values(groupedChildren)
};
};
const CustomNode = ({ nodeDatum, toggleNode }) => {
const isGroup = nodeDatum.children && nodeDatum.children.some(child => child.type === nodeDatum.name);
return (
<g>
<rect width="100" height="50" x="-50" y="-25" fill={isGroup ? "lightcoral" : "lightblue"} stroke="black" />
<text fill="black" x="-45" y="5" onClick={toggleNode}>
{nodeDatum.name}
</text>
{nodeDatum.children && (
<text fill="blue" x="-45" y="20" onClick={toggleNode}>
{`Children: ${nodeDatum.children.length}`}
</text>
)}
</g>
);
};
const MyTreeComponent = () => {
const treeData = groupByType(rawData[0]);
const boxRef = useRef(null);
const miniMapRef = useRef(null);
const [zoom, setZoom] = useState(1);
const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const handleMouseDown = (e) => {
e.preventDefault();
setIsDragging(true);
};
const handleMouseMove = (e) => {
if (!isDragging) return;
const miniMap = miniMapRef.current;
const { left, top, width, height } = miniMap.getBoundingClientRect();
const newX = Math.min(Math.max(e.clientX - left, 0), width - 20);
const newY = Math.min(Math.max(e.clientY - top, 0), height - 20);
setDragPosition({ x: newX, y: newY });
if (boxRef.current) {
const scrollableWidth = boxRef.current.scrollWidth - boxRef.current.clientWidth;
const scrollableHeight = boxRef.current.scrollHeight - boxRef.current.clientHeight;
boxRef.current.scrollLeft = (newX / (width - 20)) * scrollableWidth;
setZoom(newX*0.1);
boxRef.current.scrollTop = (newY / (height - 20)) * scrollableHeight;
}
};
const handleMouseUp = () => {
setIsDragging(false);
};
return (
<div
id="treeWrapper"
style={{ width: '100%', height: '500px', position: 'relative' }}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
>
<Box
ref={boxRef}
sx={{
width: '100%',
height: '500px',
overflow: 'auto',
border: '1px solid black',
position: 'relative',
backgroundColor: 'lightgray',
}}
>
<Tree
data={treeData1}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData2}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData3}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData4}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData5}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData6}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData7}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData8}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData9}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
<Tree
data={treeData10}
renderCustomNodeElement={(rd3tProps) => <CustomNode {...rd3tProps} />}
orientation="horizontal"
zoom={zoom}
/>
</Box>
<div
ref={miniMapRef}
className="mini-map"
style={{
position: 'absolute',
bottom: 20,
right: 20,
border: '1px solid black',
backgroundColor: 'white',
width: 100,
height: 100,
overflow: 'hidden',
}}
>
<div
style={{
position: 'absolute',
width: 20,
height: 20,
backgroundColor: 'rgba(0,0,0,0.5)',
cursor: 'pointer',
left: `${dragPosition.x}px`,
top: `${dragPosition.y}px`,
}}
onMouseDown={handleMouseDown}
/>
</div>
</div>
);
};
export default MyTreeComponent;
I want to achieve something similar to this
https://jerosoler.github.io/drawflow-minimap-example/
or
https://codesandbox.io/p/sandbox/react-flow-interactive-minimap-26u9lj?file=%2Fsrc%2Fcomponents%2FMiniMap%2FMiniMapNode.tsx
3