Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cluster Dragging #294

Merged
merged 30 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
475d519
cluster drags, nodes dont
amcdnl Nov 4, 2024
951301c
update node position on drag
amcdnl Nov 4, 2024
2f38641
add camera
amcdnl Nov 4, 2024
6871128
fix node dragging inside cluster
SerhiiTsybulskyi Nov 5, 2024
dd0a7e0
fix bug with sticking dragging
SerhiiTsybulskyi Nov 5, 2024
72e7c59
fix node speed when cluster is dragging
SerhiiTsybulskyi Nov 5, 2024
39504cb
calculate full cluster position based on new nodes positions
SerhiiTsybulskyi Nov 5, 2024
8051128
downgrade gesture lib due to bug with sticky drag
SerhiiTsybulskyi Nov 5, 2024
5ee6d49
rollback gesture lib version
SerhiiTsybulskyi Nov 5, 2024
924ddad
disable drag for not active nodes
SerhiiTsybulskyi Nov 6, 2024
eab95c0
rollback version fix
SerhiiTsybulskyi Nov 6, 2024
eca7172
add new node to dragged cluster position
SerhiiTsybulskyi Nov 6, 2024
13964ec
update method of management dragsIds
SerhiiTsybulskyi Nov 6, 2024
6257866
don't trigger hover when another node is dragging
SerhiiTsybulskyi Nov 6, 2024
f19ebd8
refactoring
SerhiiTsybulskyi Nov 6, 2024
14557c7
rollback cluster story
SerhiiTsybulskyi Nov 7, 2024
7939b38
do not allow decrease cluster when constrainDragging is enabled
SerhiiTsybulskyi Nov 7, 2024
ddc85a5
add sample with custom node
SerhiiTsybulskyi Nov 7, 2024
8b4c965
remove unnecessary flag
SerhiiTsybulskyi Nov 7, 2024
7d4b131
remove commented code
SerhiiTsybulskyi Nov 7, 2024
9b99abe
remove unnecessary brackets
SerhiiTsybulskyi Nov 7, 2024
8d0a80b
do not reset hover state on drag end
SerhiiTsybulskyi Nov 8, 2024
b73dc2a
align line position updating speed with cluster and node
SerhiiTsybulskyi Nov 8, 2024
fa3ef24
if the left mouse button is not pressed, cancel the drag
SerhiiTsybulskyi Nov 11, 2024
a6119c9
disable animation when cluster dragging
SerhiiTsybulskyi Nov 11, 2024
a70f7c0
update import
SerhiiTsybulskyi Nov 11, 2024
23d3f37
code review changes
SerhiiTsybulskyi Nov 12, 2024
91ae32d
remove double spreading
SerhiiTsybulskyi Nov 12, 2024
4c6f41d
code review changes
SerhiiTsybulskyi Nov 13, 2024
a8d11a0
move comment few lines above
SerhiiTsybulskyi Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 297 additions & 3 deletions docs/demos/Cluster.story.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react';
import { GraphCanvas, lightTheme } from '../../src';
import { GraphCanvas, Icon, lightTheme, Sphere } from '../../src';
import {
clusterNodes,
clusterEdges,
Expand All @@ -9,13 +9,275 @@ import {
manyClusterNodes
} from '../assets/demo';

import demonSvg from '../../docs/assets/twitter.svg';

export default {
title: 'Demos/Cluster',
component: GraphCanvas
};

export const Simple = () => {
const [nodes, setNodes] = useState(clusterNodes);
const [nodes, setNodes] = useState([
{
id: 'n-0',
label: 'MD5 0',
fill: '#075985',
data: {
type: 'MD5',
segment: 'A'
}
},
{
id: 'n-1',
label: 'Email 1',
fill: '#166534',
data: {
type: 'Email'
}
},
{
id: 'n-2',
label: 'MD5 2',
fill: '#075985',
data: {
type: 'MD5',
segment: 'A'
}
},
{
id: 'n-3',
label: 'URL 3',
fill: '#c2410c',
data: {
type: 'URL'
}
},
{
id: 'n-4',
label: 'MD5 4',
fill: '#075985',
data: {
type: 'MD5',
segment: 'A'
}
},
{
id: 'n-5',
label: 'MD5 5',
fill: '#075985',
data: {
type: 'MD5'
}
},
{
id: 'n-6',
label: 'IP 6',
fill: '#3730a3',
data: {
type: 'IP',
segment: 'A'
}
},
{
id: 'n-7',
label: 'IP 7',
fill: '#3730a3',
data: {
type: 'IP'
}
},
{
id: 'n-8',
label: 'URL 8',
fill: '#c2410c',
data: {
type: 'URL',
segment: 'A'
}
},
{
id: 'n-9',
label: 'MD5 9',
fill: '#075985',
data: {
type: 'MD5'
}
},
{
id: 'n-10',
label: 'URL 10',
fill: '#c2410c',
data: {
type: 'URL',
segment: 'A'
}
},
{
id: 'n-11',
label: 'URL 11',
fill: '#c2410c',
data: {
type: 'URL'
}
},
{
id: 'n-12',
label: 'URL 12',
fill: '#c2410c',
data: {
type: 'URL',
segment: 'A'
}
},
{
id: 'n-13',
label: 'Email 13',
fill: '#166534',
data: {
type: 'Email'
}
},
{
id: 'n-14',
label: 'URL 14',
fill: '#c2410c',
data: {
type: 'URL',
segment: 'A'
}
},
{
id: 'n-15',
label: 'IP 15',
fill: '#3730a3',
data: {
type: 'IP'
}
},
{
id: 'n-16',
label: 'Email 16',
fill: '#166534',
data: {
type: 'Email',
segment: 'A'
}
},
{
id: 'n-17',
label: 'Email 17',
fill: '#166534',
data: {
type: 'Email'
}
},
{
id: 'n-18',
label: 'URL 18',
fill: '#c2410c',
data: {
type: 'URL',
segment: 'A'
}
},
{
id: 'n-19',
label: 'Email 19',
fill: '#166534',
data: {
type: 'Email'
}
},
{
id: 'n-20',
label: 'Email 20',
fill: '#166534',
data: {
type: 'Email',
segment: 'A'
}
},
{
id: 'n-21',
label: 'Email 21',
fill: '#166534',
data: {
type: 'Email'
}
},
{
id: 'n-22',
label: 'Email 22',
fill: '#166534',
data: {
type: 'Email',
segment: 'A'
}
},
{
id: 'n-23',
label: 'URL 23',
fill: '#c2410c',
data: {
type: 'URL'
}
},
{
id: 'n-24',
label: 'Email 24',
fill: '#166534',
data: {
type: 'Email',
segment: 'A'
}
}
] as any);

const addNode = useCallback(() => {
const next = nodes.length + 2;
setNodes(prev => [
...prev,
{
id: `${next}`,
label: `Node ${next}`,
fill: '#3730a3',
data: {
type: 'IP',
segment: next % 2 === 0 ? 'A' : undefined
}
}
]);
}, [nodes]);

return (
<>
<GraphCanvas
nodes={nodes}
draggable
edges={[
{
source: 'n-6',
target: 'n-1',
id: 'n-6-n-1',
label: 'n-6-n-1'
}
]}
clusterAttribute="type"
constrainDragging={false}
/>
<div style={{ zIndex: 9, position: 'absolute', top: 15, right: 15 }}>
<button type="button" onClick={addNode}>
Add node
</button>
</div>
</>
);
};

export const SimpleRenderNode = () => {
const [nodes, setNodes] = useState(
clusterNodes.map(n => ({ ...n, icon: demonSvg }))
);

const addNode = useCallback(() => {
const next = nodes.length + 2;
Expand All @@ -25,6 +287,7 @@ export const Simple = () => {
id: `${next}`,
label: `Node ${next}`,
fill: '#3730a3',
icon: demonSvg,
data: {
type: 'IP',
segment: next % 2 === 0 ? 'A' : undefined
Expand All @@ -35,7 +298,38 @@ export const Simple = () => {

return (
<>
<GraphCanvas nodes={nodes} draggable edges={[]} clusterAttribute="type" constrainDragging />
<GraphCanvas
nodes={nodes}
draggable
edges={[]}
clusterAttribute="type"
constrainDragging={false}
renderNode={node => (
<group>
amcdnl marked this conversation as resolved.
Show resolved Hide resolved
<Sphere
id={node.id}
size={node.size}
opacity={0.5}
animated={false}
color="purple"
node={node.node}
active={false}
selected={node.selected}
></Sphere>
<Icon
id={node.id}
image={demonSvg}
size={node.size}
opacity={1}
animated={false}
color="red"
node={node.node}
active={false}
selected={node.selected}
/>
</group>
)}
/>
<div style={{ zIndex: 9, position: 'absolute', top: 15, right: 15 }}>
<button type="button" onClick={addNode}>
Add node
Expand Down
27 changes: 24 additions & 3 deletions src/CameraControls/CameraControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import React, {
Ref,
useImperativeHandle,
useMemo,
ReactNode
ReactNode,
useState
} from 'react';
import { useThree, useFrame, extend } from '@react-three/fiber';
import {
Expand Down Expand Up @@ -117,6 +118,9 @@ export const CameraControls: FC<
const isOrbiting = mode === 'orbit';
const setPanning = useStore(state => state.setPanning);
const isDragging = useStore(state => state.draggingIds.length > 0);
const [cameraSpeed, setCameraSpeed] = useState(
SerhiiTsybulskyi marked this conversation as resolved.
Show resolved Hide resolved
cameraRef.current?.truckSpeed ?? 0
);

useFrame((_state, delta) => {
if (cameraRef.current?.enabled) {
Expand Down Expand Up @@ -325,10 +329,27 @@ export const CameraControls: FC<
panDown: (deltaTime = 100) => panDown({ deltaTime }),
panUp: (deltaTime = 100) => panUp({ deltaTime }),
resetControls: (animated?: boolean) =>
cameraRef.current?.reset(animated)
cameraRef.current?.reset(animated),
freeze: () => {
// Save the current speed
if (cameraRef.current.truckSpeed) {
setCameraSpeed(cameraRef.current.truckSpeed);
}
cameraRef.current.truckSpeed = 0;
},
unFreeze: () => (cameraRef.current.truckSpeed = cameraSpeed)
}),
// eslint-disable-next-line
[zoomIn, zoomOut, panLeft, panRight, panDown, panUp, cameraRef.current]
[
zoomIn,
zoomOut,
panLeft,
panRight,
panDown,
panUp,
cameraRef.current,
cameraSpeed
]
);

useImperativeHandle(ref, () => values);
Expand Down
Loading
Loading