From 5953227c1bf3f1f4faddd94558ffe15d47029a2e Mon Sep 17 00:00:00 2001 From: Nikita Rokotyan Date: Wed, 19 Mar 2025 13:47:00 -0700 Subject: [PATCH 1/8] Component | Graph: Update link flow configuration to use NumericAccessor - Changed `linkFlowAnimDuration` and `linkFlowParticleSize` to use `NumericAccessor` for better flexibility. - Updated related calculations in the `_onLinkFlowTimerFrame` and `updateLinks` functions to accommodate the new accessor type. --- packages/ts/src/components/graph/config.ts | 5 ++--- packages/ts/src/components/graph/index.ts | 13 +++++++------ .../ts/src/components/graph/modules/link/index.ts | 13 +++++++------ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/ts/src/components/graph/config.ts b/packages/ts/src/components/graph/config.ts index 61aa6ff77..4eea3ec58 100644 --- a/packages/ts/src/components/graph/config.ts +++ b/packages/ts/src/components/graph/config.ts @@ -34,7 +34,6 @@ import { GraphNodeSelectionHighlightMode, } from './types' - export interface GraphConfigInterface extends ComponentConfigInterface { // Zoom and drag /** Zoom level constraints. Default: [0.35, 1.25] */ @@ -143,9 +142,9 @@ export interface GraphConfigInterface; /** Animation duration of the flow (traffic) circles. Default: `20000` */ - linkFlowAnimDuration?: number; + linkFlowAnimDuration?: NumericAccessor; /** Size of the moving particles that represent traffic flow. Default: `2` */ - linkFlowParticleSize?: number; + linkFlowParticleSize?: NumericAccessor; /** Link label accessor function or constant value. Default: `undefined` */ linkLabel?: GenericAccessor | undefined; /** Shift label along the link center a little bit to avoid overlap with the link arrow. Default: `true` */ diff --git a/packages/ts/src/components/graph/index.ts b/packages/ts/src/components/graph/index.ts index 3d14caac6..024bff98b 100644 --- a/packages/ts/src/components/graph/index.ts +++ b/packages/ts/src/components/graph/index.ts @@ -15,7 +15,7 @@ import { GraphInputLink, GraphInputNode, GraphInputData } from 'types/graph' import { Spacing } from 'types/spacing' // Utils -import { isNumber, clamp, shallowDiff, isFunction, getBoolean, isPlainObject, isEqual } from 'utils/data' +import { isNumber, clamp, shallowDiff, isFunction, getBoolean, isPlainObject, isEqual, getNumber } from 'utils/data' import { smartTransition } from 'utils/d3' // Local Types @@ -661,16 +661,17 @@ export class Graph< } private _onLinkFlowTimerFrame (elapsed = 0): void { - const { config: { linkFlow, linkFlowAnimDuration }, datamodel: { links } } = this + const { config, datamodel: { links } } = this - const hasLinksWithFlow = links.some((d, i) => getBoolean(d, linkFlow, i)) + const hasLinksWithFlow = links.some((d, i) => getBoolean(d, config.linkFlow, i)) if (!hasLinksWithFlow) return - const t = (elapsed % linkFlowAnimDuration) / linkFlowAnimDuration const linkElements = this._linksGroup.selectAll>(`.${linkSelectors.gLink}`) - const linksToAnimate = linkElements.filter(d => !d._state.greyout) - linksToAnimate.each(d => { d._state.flowAnimTime = t }) + linksToAnimate.each((l, i, els) => { + const linkFlowAnimDuration = getNumber(l, config.linkFlowAnimDuration, l._indexGlobal) + l._state.flowAnimTime = (elapsed % linkFlowAnimDuration) / linkFlowAnimDuration + }) animateLinkFlow(linksToAnimate, this.config, this._scale, this._linkPathLengthMap) } diff --git a/packages/ts/src/components/graph/modules/link/index.ts b/packages/ts/src/components/graph/modules/link/index.ts index b40c20973..e42b00733 100644 --- a/packages/ts/src/components/graph/modules/link/index.ts +++ b/packages/ts/src/components/graph/modules/link/index.ts @@ -180,7 +180,7 @@ export function updateLinks getLinkArrowDefId: (arrow: GraphLinkArrowStyle | undefined) => string, linkPathLengthMap: Map ): void { - const { linkFlowParticleSize, linkStyle, linkFlow, linkLabel, linkLabelShiftFromCenter } = config + const { linkStyle, linkFlow, linkLabel, linkLabelShiftFromCenter } = config if (!selection.size()) return selection @@ -204,6 +204,7 @@ export function updateLinks const linkLabelData = ensureArray( getValue, GraphCircleLabel | GraphCircleLabel[]>(d, linkLabel, d._indexGlobal) ) + const linkFlowParticleSize = getNumber(d, config.linkFlowParticleSize, d._indexGlobal) // Particle Flow flowGroup @@ -212,7 +213,7 @@ export function updateLinks flowGroup .selectAll(`.${linkSelectors.flowCircle}`) - .attr('r', linkFlowParticleSize / scale) + .attr('r', linkFlowParticleSize / Math.sqrt(scale)) .style('fill', linkColor) smartTransition(flowGroup, duration) @@ -387,15 +388,15 @@ export function zoomLinks ( config: GraphConfigInterface, scale: number ): void { - const { linkFlowParticleSize } = config - selection.classed(generalSelectors.zoomOutLevel2, scale < ZoomLevel.Level2) selection.select(`.${linkSelectors.flowGroup}`) .style('opacity', scale < ZoomLevel.Level2 ? 0 : 1) - selection.selectAll(`.${linkSelectors.flowCircle}`) - .attr('r', linkFlowParticleSize / scale) + selection.each((l, i, els) => { + const r = getNumber(l, config.linkFlowParticleSize, l._indexGlobal) / Math.sqrt(scale) + select(els[i]).selectAll(`.${linkSelectors.flowCircle}`).attr('r', r) + }) const linkElements = selection.selectAll>(`.${linkSelectors.link}`) linkElements From e2675ed8dc69b1d7eff85ef28e714391228a1cae Mon Sep 17 00:00:00 2001 From: Nikita Rokotyan Date: Wed, 19 Mar 2025 13:48:15 -0700 Subject: [PATCH 2/8] Dev | Examples | Graph | Custom Nodes: Enhance link flow configuration with animation duration and particle size - Added `linkFlowAnimDuration` and `linkFlowParticleSize` properties to `CustomGraphLink` type for improved customization of link animations. - Updated example implementation to utilize the new properties for better visual representation of link flows. --- .../graph/graph-custom-node-rendering/index.tsx | 13 +++++++------ .../graph/graph-custom-node-rendering/types.ts | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/dev/src/examples/networks-and-flows/graph/graph-custom-node-rendering/index.tsx b/packages/dev/src/examples/networks-and-flows/graph/graph-custom-node-rendering/index.tsx index f9a284780..417af0a99 100644 --- a/packages/dev/src/examples/networks-and-flows/graph/graph-custom-node-rendering/index.tsx +++ b/packages/dev/src/examples/networks-and-flows/graph/graph-custom-node-rendering/index.tsx @@ -35,11 +35,11 @@ export const component = (): JSX.Element => { ]), []) const links: CustomGraphLink[] = useMemo(() => ([ - { source: '0', target: '1', showFlow: true }, - { source: '0', target: '2', showFlow: true }, - { source: '0', target: '3', showFlow: true }, - { source: '0', target: '4', showFlow: true }, - { source: '1', target: '5', showFlow: true }, + { source: '0', target: '1', showFlow: true, linkFlowAnimDuration: 10000, linkFlowParticleSize: 1.5 }, + { source: '0', target: '2', showFlow: true, linkFlowAnimDuration: 10000, linkFlowParticleSize: 2 }, + { source: '0', target: '3', showFlow: true, linkFlowAnimDuration: 10000, linkFlowParticleSize: 3 }, + { source: '0', target: '4', showFlow: true, linkFlowAnimDuration: 10000, linkFlowParticleSize: 3 }, + { source: '1', target: '5', showFlow: true, linkFlowAnimDuration: 5000, linkFlowParticleSize: 2.5 }, ]), []) // Modifying layout after the calculation @@ -61,7 +61,8 @@ export const component = (): JSX.Element => { height={'100vh'} linkFlow={useCallback((l: CustomGraphLink) => showLinkFlow && l.showFlow, [showLinkFlow])} onLayoutCalculated={onLayoutCalculated} - + linkFlowAnimDuration={useCallback((l: CustomGraphLink) => l.linkFlowAnimDuration, [])} + linkFlowParticleSize={useCallback((l: CustomGraphLink) => l.linkFlowParticleSize, [])} />