[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:node-styling-techniques":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Comparing Node Styling Techniques in One Graph\n\n## What This Example Builds\n\nThis example builds a compact relation-graph scene whose main purpose is to compare several node presentation techniques in one canvas. The viewer sees circular and rectangular nodes, nodes with explicit size overrides, fit-content nodes, one fixed-position node, a logo-backed custom node, and a CSS-animated node.\n\nThe graph is presented as a read-only styling reference rather than a domain workflow. Users can inspect the prepared variants, open the floating settings panel, switch wheel and drag behavior, drag or minimize the helper window, export the graph as an image, and use the mini view for navigation. Node and line clicks are wired, but in this example they only log the selected objects.\n\n## How the Data Is Organized\n\nThe graph data is assembled inline as one `RGJsonData` object inside `initializeGraph()`. It sets `rootId: 'a'`, defines eleven nodes, and connects them with eleven lines before the payload is loaded through `setJsonData()`.\n\nThe important point is that the dataset already carries many of the visual differences. Individual node records override fields such as `width`, `height`, `borderWidth`, `borderColor`, `color`, `fontColor`, `nodeShape`, `fixed`, `x`, `y`, `type`, and `className`. That makes the data layer a direct vehicle for style comparison before any slot logic runs.\n\nIn a real product, the same pattern could encode business meaning instead of demo labels. The per-node fields could represent emphasis levels, category colors, avatar or logo placeholders, pinned reference nodes, compact summary cards, or alert states that need animation.\n\n## How relation-graph Is Used\n\nThe example uses the built-in `center` layout and sets graph-wide defaults for circular nodes, curved lines, border junction points, and an `80 x 80` default node size. Those defaults establish a common baseline, while the JSON data overrides only the nodes that need a different treatment.\n\n`RGHooks.useGraphInstance()` drives the graph lifecycle. On mount, the component loads the inline data with `setJsonData()`, then normalizes the viewport with `moveToCenter()` and `zoomToFit()`. The same hook is reused inside the shared settings panel so the demo can update runtime options and prepare the canvas for image export.\n\nCustomization is split across slots, shared subcomponents, and CSS. `RGSlotOnNode` mounts a `NodeSlot` renderer that switches on `node.id` and `node.type` to produce special node bodies. `RGSlotOnView` adds `RGMiniView` as an overlay. `RGProvider` wraps the whole example so hooks can access the active graph instance. The floating `DraggableWindow` contributes the description shell and hosts `CanvasSettingsPanel`, which reads the current store state and changes `wheelEventAction` or `dragEventAction` through `setOptions()`. The animated node variant comes from the imported `simple-node-animations.scss` stylesheet, while the image-backed and plain-text variants use inline styles inside the node slot.\n\n## Key Interactions\n\n- The graph loads once on mount and immediately centers and fits the prepared dataset, so the full style gallery is visible without manual setup.\n- Clicking a node or line triggers handlers, but those handlers only log the selected object. They are diagnostic hooks, not feature entry points.\n- The floating helper window can be dragged from its header and toggled between expanded and minimized states.\n- Opening the settings overlay exposes graph-level controls for wheel behavior (`scroll`, `zoom`, or `none`) and canvas drag behavior (`selection`, `move`, or `none`).\n- The `Download Image` action prepares the graph canvas, captures it as a blob, triggers a download, and then restores the graph state.\n- `RGMiniView` gives the example a minimap overlay, which is useful because the scene mixes differently sized nodes and includes one pinned node with explicit coordinates.\n\n## Key Code Fragments\n\nThis fragment shows that the baseline graph configuration is intentionally simple, so node-level overrides are easy to compare.\n\n```tsx\nconst graphOptions: RGOptions = {\n    layout: {\n        layoutName: 'center'\n    },\n    defaultNodeShape: RGNodeShape.circle,\n    defaultLineShape: RGLineShape.StandardCurve,\n    defaultJunctionPoint: RGJunctionPoint.border,\n    defaultNodeWidth: 80,\n    defaultNodeHeight: 80,\n};\n```\n\nThis fragment shows how the example encodes visual differences directly in the JSON payload before the graph renders.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: 'a',\n    nodes: [\n        { id: 'a', text: 'Border color', width: 150, height: 150, borderColor: '#f43ce5', borderWidth: 3 },\n        { id: 'a1-1', text: 'Plain Text Node', borderWidth: 0, width: 0, height: 0, nodeShape: RGNodeShape.rect },\n        { id: 'e', text: 'Node width/height fit-content ', width: 0, height: 0, nodeShape: RGNodeShape.rect },\n        { id: 'f1', text: 'Fixed', fixed: true, x: -660, y: -160 },\n        { id: 'g', type: 'my-animation', text: 'Css Animation', width: 0, height: 0, className: 'my-node-flash-style' }\n    ],\n    // ...\n};\n```\n\nThis fragment shows the mount-time graph lifecycle: load the prepared data, then normalize the viewport.\n\n```tsx\nconst initializeGraph = async () => {\n    // ...\n    await graphInstance.setJsonData(myJsonData);\n    graphInstance.moveToCenter();\n    graphInstance.zoomToFit();\n};\n\nuseEffect(() => {\n    initializeGraph();\n}, []);\n```\n\nThis fragment shows that `RGSlotOnNode` is not used for one uniform skin. It branches to render several unrelated node-body variants in the same graph.\n\n```tsx\nconst NodeSlot: React.FC\u003CRGNodeSlotProps> = ({ node }) => {\n    if (node.id === 'a1-1') {\n        return \u003Cdiv style={{ color: '#ff8c00', display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>{node.text}\u003C/div>;\n    }\n    if (node.id === 'a1-4') {\n        return \u003Cdiv style={{ border: '#ff8c00 solid 6px', height: '100%', width: '100%', borderRadius: '40px', backgroundImage: `url(${rgLogoUrl})`, backgroundPosition: 'center center', backgroundColor: '#fff' }} />;\n    }\n    if (node.type === 'my-animation') {\n        return \u003Cdiv className=\"my-node-animation-01 h-32 w-32 rounded-full relative text-lg flex place-items-center justify-center overflow-hidden\">{/* ... */}\u003C/div>;\n    }\n    return \u003Cdiv style={{ padding: '5px 10px', height: '100%', width: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center', color: node.fontColor || 'inherit' }}>{node.text}\u003C/div>;\n};\n```\n\nThis fragment shows that the animated node appearance comes from a reusable CSS class rather than from repeated inline style declarations.\n\n```scss\n.my-node-animation-01 {\n    background: linear-gradient(\n            to bottom,\n            #00ffff,\n            #ff00ff,\n            #00ffff\n    );\n    background-size: 100% 200%;\n    animation: gradient-flow 6s ease-in-out infinite;\n}\n```\n\nThis fragment shows how the shared settings panel turns the example into a viewer utility shell with runtime interaction toggles and image export.\n\n```tsx\n\u003CSettingRow\n    label=\"Wheel Event:\"\n    options={[\n        { label: 'Scroll', value: 'scroll' },\n        { label: 'Zoom', value: 'zoom' },\n        { label: 'None', value: 'none' },\n    ]}\n    value={wheelMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n\u003CSettingRow\n    label=\"Canvas Drag Event:\"\n    options={[\n        { label: 'Selection', value: 'selection' },\n        { label: 'Move', value: 'move' },\n        { label: 'none', value: 'none' },\n    ]}\n    value={dragMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ dragEventAction: newValue }); }}\n/>\n\u003CSimpleUIButton onClick={downloadImage}>\n    Download Image\n\u003C/SimpleUIButton>\n```\n\n## What Makes This Example Distinct\n\nCompared with nearby examples such as `node-style3` and `node-style4`, this example is broader and less theme-driven. Those examples lean toward one coherent custom slot skin, while `node` uses one canvas to compare several styling paths side by side: per-node JSON overrides, targeted slot-rendered exceptions, fit-content rectangles, an image-backed node, a CSS-animated node, and a fixed-position node.\n\nCompared with `line`, the overall teaching pattern is similar, but the comparison target is different. `line` uses the same static gallery approach for edge geometry and markers, while `node` redirects it toward node appearance, sizing, shape, text styling, and custom body rendering.\n\nCompared with `layout-tree`, the shared viewer shell is not the main lesson. This example does include the floating helper window and `RGMiniView`, but the comparison data shows that its distinctive value is fixed style comparison on a stable layout, not runtime relayout or orientation switching.\n\nThe most unusual combination is that it stays on a normal viewer path while mixing many node-style techniques in one small graph. It does not present itself as a full editor, and it does not rely only on slots. The visible result comes from the combination of built-in per-node visual fields, slot-level exceptions, CSS animation, and lightweight viewer utilities.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to design-system documentation for graph UIs. A team can use one prepared graph to compare status badges, severity colors, pinned nodes, avatar nodes, media-backed nodes, and animated warning states before those styles are applied in a production workflow.\n\nIt also fits internal tooling where stakeholders need to validate node treatments without editing graph structure. Examples include knowledge-graph theming reviews, network monitoring dashboards, dependency maps, and organization charts where the main question is how different node categories should look rather than how the layout should behave.\n\nThe same structure is also useful as a regression board. Because the graph loads fixed sample nodes with known size, shape, and slot variants, it can act as a compact visual test surface whenever a team changes relation-graph theme rules, slot renderers, or export behavior.\n",false,500,1782615370797]