[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:graph-line-animation-presets":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Preset-Driven Animated Graph Lines\n\n## What This Example Builds\n\nThis example builds a left-to-right relation graph tree on a dark canvas and turns the links into an animation gallery. The nodes stay small and icon-focused, while the lines carry most of the visual behavior through twelve selectable presets.\n\nUsers can switch among basic, pipeline, and SVG-filter-based line styles from a floating control window. They can also drag or minimize that window, open a shared settings overlay to change wheel and drag behavior, and export the graph as an image. The main point is that the demo achieves all of this by restyling relation-graph's built-in line surfaces instead of replacing the line renderer.\n\n## How the Data Is Organized\n\nThe graph data is assembled inline inside `initializeGraph()` as a static `RGJsonData` object. It has one `rootId`, a `nodes` array with `id`, `text`, and `data.icon`, and a `lines` array with explicit `id`, `from`, `to`, and `text` fields.\n\nThere is no structural preprocessing before `setJsonData()`. The only meaningful transformation is the icon lookup layer: `node.data.icon` is mapped to a Lucide component in `IconMapper`, and the selected line preset is applied after load by mutating every existing line. In a real application, the same shape could represent service dependencies, production stages, supply routes, or approval flows where the topology stays stable but the visual state needs to change at runtime.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the example in `RGProvider`, and `MyGraph.tsx` renders `RelationGraph` with a tree layout that grows from the left. The options fix the visual shell: circular nodes, curved lines, left-right junction points, explicit horizontal and vertical tree gaps, a transparent node body, and a bottom-right horizontal toolbar.\n\nThe example uses `RGHooks.useGraphInstance()` as the runtime control surface. That instance loads the static JSON, centers the graph, fits it to the viewport, reads the current lines with `getLines()`, rewrites them with `updateLine()`, and supports export through `prepareForImageGeneration()` and `restoreAfterImageGeneration()`. The shared settings overlay uses `RGHooks.useGraphStore()` to read the current wheel and drag modes, then calls `setOptions()` to switch them.\n\nThe custom rendering hook is `RGSlotOnNode`. Instead of replacing edges, the example keeps the native relation-graph line renderer and overrides only the node content with icon-based circular bodies. Styling work happens in SCSS: `.rg-map` and `.rg-toolbar` set the dark shell, `.rg-node-peel.rg-node-checked` and `.rg-line-peel.rg-line-checked` adjust checked states, and twelve `.my-line-class-xx` selectors retheme `.rg-line`, `.rg-line-bg`, `.rg-line-label`, and `.rg-line-text`. `MySvgFilters` injects the `rough-paper`, `electric-glitch`, and `gooey-plasma` filter definitions required by the filter-backed presets, and wrapper classes such as `current-animation-is-10` keep node accents aligned with the active line style.\n\n## Key Interactions\n\n- Choosing a preset in any `SimpleUISelect` rewrites every line's `className` and visible text, so the whole graph switches style at once.\n- Initial load is also interactive: after `setJsonData()`, the graph is centered, fitted, and immediately switched to preset `10`, so the demo opens in a fully styled state.\n- The floating control window can be dragged by its title bar, minimized, and reopened without affecting the graph itself.\n- The settings overlay changes `wheelEventAction` between `scroll`, `zoom`, and `none`, and changes `dragEventAction` between `selection`, `move`, and `none`.\n- The export action prepares the graph DOM for capture, renders it to a Blob through `modern-screenshot`, downloads the image, and restores the graph state afterward.\n\n## Key Code Fragments\n\nThis fragment shows that the demo relies on relation-graph's built-in layout and renderer settings rather than custom geometry.\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultLineColor: 'rgba(255, 255, 255, 0.6)',\n    defaultNodeColor: 'transparent',\n    defaultNodeShape: RGNodeShape.circle,\n    defaultLineShape: RGLineShape.StandardCurve,\n    defaultJunctionPoint: RGJunctionPoint.lr,\n    layout: {\n        layoutName: 'tree',\n        from: 'left',\n        treeNodeGapH: 310,\n        treeNodeGapV: 70\n    }\n};\n```\n\nThis fragment shows that one fixed dataset is loaded once, then styled after the graph is already on screen.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: 'a',\n    nodes: [\n        // node records omitted\n    ],\n    lines: [\n        // line records omitted\n    ]\n};\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\nchangeAllLineClassName('10');\n```\n\nThis fragment is the core technique: it batch-updates every existing line through the graph instance API.\n\n```tsx\nconst changeAllLineClassName = (newClassName: string) => {\n    setLineAnimation(newClassName);\n    const allLines = graphInstance.getLines();\n    allLines.forEach(line => {\n        graphInstance.updateLine(line.id, {\n            className: `my-line-class-${newClassName}`,\n            text: `className=${newClassName}`\n        });\n    });\n};\n```\n\nThis fragment shows that the example customizes nodes through a slot while leaving edge rendering to relation-graph itself.\n\n```tsx\n\u003CRGSlotOnNode>\n    {({ node }: RGNodeSlotProps) => {\n        const iconName = node.data?.icon || 'default';\n        const IconComponent = IconMapper[iconName] || CircleDot;\n        return (\n            \u003Cdiv className=\"my-icon-node rounded-full h-20 w-20 text-white rounded flex place-items-center justify-center hover:bg-white hover:bg-opacity-40\">\n                \u003CIconComponent size={40} strokeWidth={1.5} />\n            \u003C/div>\n        );\n    }}\n\u003C/RGSlotOnNode>\n```\n\nThis fragment proves that some presets are not pure CSS decoration; they depend on injected SVG filter definitions.\n\n```tsx\n\u003Cfilter id=\"electric-glitch\">\n    \u003CfeTurbulence type=\"turbulence\" baseFrequency=\"0.05\" numOctaves=\"2\" result=\"turbulence\">\n        \u003Canimate attributeName=\"baseFrequency\" dur=\"0.1s\" values=\"0.01;0.5;0.02\"\n            repeatCount=\"indefinite\"/>\n    \u003C/feTurbulence>\n    \u003CfeDisplacementMap in=\"SourceGraphic\" in2=\"turbulence\" scale=\"10\" xChannelSelector=\"R\"\n        yChannelSelector=\"G\"/>\n\u003C/filter>\n```\n\nThis fragment shows how one preset binds those filter defs to relation-graph's native line layers.\n\n```scss\n.rg-line-peel.my-line-class-10 {\n    .rg-line-bg {\n        stroke: #f43ce5;\n        filter: url(#electric-glitch);\n    }\n\n    .rg-line {\n        stroke: $glitch-color;\n        animation: glitch-slide-10 0.2s steps(2) infinite;\n        filter: url(#electric-glitch);\n    }\n}\n```\n\n## What Makes This Example Distinct\n\nThe comparison data positions this demo as a preset gallery for animated built-in edges, not as a generic line-customization sample. Its rare point is the way it turns one fixed tree into twelve switchable styles by batch-updating every line's `className` from a floating panel.\n\nCompared with `custom-line-style`, it pushes further on motion variety by grouping presets into basic, pipeline, and SVG-filter families instead of stopping at a smaller CSS-first skin set. Compared with `line-style1`, it does not rely on static `dashType` and `animation` values embedded in `RGJsonData`; it rethemes the already-loaded graph through `getLines()` and `updateLine()`. Compared with `line-style2`, it changes the entire graph at once instead of emphasizing only the checked edge. Compared with `customer-line1`, it stays on relation-graph's native line renderer instead of replacing edge geometry with slot-rendered ribbons.\n\nAnother distinctive detail is the coordinated presentation layer. The SCSS preset classes handle the lines, labels, and text, while wrapper classes such as `current-animation-is-01`, `10`, `11`, and `12` recolor node icons to match the selected effect. That makes the example a compact reference for whole-graph visual theming rather than a single isolated animation trick.\n\n## Where Else This Pattern Applies\n\n- A network operations screen could keep one dependency graph and switch line skins to represent idle, degraded, congested, and failing traffic modes without rebuilding the data.\n- A logistics or manufacturing dashboard could reuse the same topology while changing line motion to suggest oil flow, coolant circulation, energy transfer, or blocked transport.\n- A design-system playground could use the same technique as an edge-style catalog, where product teams compare several branded line treatments on one stable example graph.\n- A workflow or approval viewer could map line presets to runtime states such as normal throughput, escalation, review backlog, or bidirectional synchronization, while keeping the node layout unchanged.\n",false,500,1782615375939]