[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:center-layout-spacing-controls":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Tuning Center Layout Spacing at Runtime\n\n## What This Example Builds\n\nThis example builds a full-viewport relation graph demo for the `center` layout, with a floating control window layered above the canvas. The graph itself is a fixed branching hierarchy rendered as small teal circles connected by teal lines, so layout changes remain easy to see.\n\nUsers can switch between two spacing strategies. One mode changes a single `distanceCoefficient` value with a slider, and the other mode edits explicit per-level gaps through a comma-separated text field plus preset shortcuts. The same floating window also supports dragging, minimizing, opening a canvas-settings overlay, and exporting the current graph view as an image.\n\nThe main point is not the sample data. The main point is that the exact same hierarchy can be relaid out live with either a global spacing multiplier or a per-level spacing array.\n\n## How the Data Is Organized\n\nThe graph data is declared inline as one `RGJsonData` object with `rootId: 'a'`, a `nodes` array, and a `lines` array. There is no preprocessing step for the graph payload before `setJsonData()` runs. Initialization simply loads the static dataset, centers the viewport, and fits the graph to the available space.\n\nThe only runtime preprocessing in this example is for layout parameters, not graph data. In level-distance mode, the `levelDistance` string is split on commas, converted with `parseInt`, and passed to `layout.levelGaps`.\n\nIn real projects, this same shape can stand in for organizational levels, product category trees, capability maps, dependency trees, or any hierarchy where different depth levels need different visual spacing.\n\n## How relation-graph Is Used\n\nThe page is wrapped in `RGProvider`, and both the example component and the shared settings panel read the active graph instance with `RGHooks.useGraphInstance()`. The graph is rendered through `RelationGraph`, using a small initial options object rather than custom node or line slots.\n\nThe initial graph options set `layout.layoutName` to `center`, disable debug output, and define the main visual defaults in code: 50x50 nodes, circular node shape, no node border, and teal colors for nodes and lines. After mount, the component loads the inline hierarchy with `setJsonData()`, then calls `moveToCenter()` and `zoomToFit()`.\n\nRuntime layout changes are handled by rebuilding only the `layout` portion of the options. When `configType === 1`, the code writes `distanceCoefficient`; otherwise it parses the comma-separated input and writes `levelGaps`. It then applies the layout with `setOptions({ layout })` and explicitly calls `doLayout()`.\n\nThe floating utility window comes from the shared `DraggableWindow` component. That component also uses `RGHooks.useGraphStore()` and `setOptions()` to switch `wheelEventAction` and `dragEventAction`, and it uses `prepareForImageGeneration()`, `getOptions()`, and `restoreAfterImageGeneration()` during screenshot export.\n\nThis example does not use relation-graph slots, custom node templates, or editing APIs. A local stylesheet is imported and defines checked-state overrides under a `.my-graph` scope, but the visible customization in this demo mainly comes from graph options and the shared floating window.\n\n## Key Interactions\n\nThe primary interaction is the mode toggle between two spacing strategies. The selector shows either a range slider for `distanceCoefficient` or a text-driven `levelGaps` editor, never both at once.\n\nIn coefficient mode, dragging the slider updates React state and immediately triggers a new layout pass. In level-gap mode, users can type a comma-separated list such as `100,150,200,250,300`, or click one of the preset strings to push a ready-made spacing pattern into the same state variable.\n\nThe graph data stays read-only, but the workspace itself remains interactive. The floating control window can be dragged and minimized, its settings overlay can switch wheel and drag behavior on the canvas, and the same overlay can export the current graph image.\n\n## Key Code Fragments\n\nThis fragment shows that the demo starts with the `center` layout and keeps the visual defaults intentionally simple so spacing changes remain the main signal.\n\n```tsx\nconst graphOptions: RGOptions = {\n  debug: false,\n  defaultNodeWidth: 50,\n  defaultNodeHeight: 50,\n  defaultLineColor: 'rgba(0, 186, 189, 1)',\n  defaultNodeColor: 'rgba(0, 206, 209, 1)',\n  defaultNodeShape: RGNodeShape.circle,\n  defaultNodeBorderWidth: 0,\n  layout: {\n    layoutName: 'center',\n    distanceCoefficient: 1\n  }\n};\n```\n\nThis fragment shows that the graph payload is a fixed inline hierarchy that is loaded once and then centered and fitted in the viewport.\n\n```tsx\nconst myJsonData: RGJsonData = {\n  rootId: 'a',\n  nodes: [\n    { id: 'a', text: 'a' },\n    { id: 'b', text: 'b' },\n    { id: 'b1', text: 'b1' },\n    // ...\n  ],\n  lines: [\n    { id: 'l-1', from: 'a', to: 'b' },\n    { id: 'l-2', from: 'b', to: 'b1' },\n    // ...\n  ]\n};\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis fragment proves that the example compares two layout-spacing modes by rebuilding only the layout options and rerunning `doLayout()`.\n\n```tsx\nconst layoutOptions: RGLayoutOptions = {\n  layoutName: 'center'\n};\n\nif (configType === 1) {\n  layoutOptions.distanceCoefficient = distanceCoefficient;\n} else {\n  const _levelDistance = levelDistance.split(',').map(i => parseInt(i, 10));\n  layoutOptions.levelGaps = _levelDistance;\n}\n\ngraphInstance.setOptions({\n  layout: layoutOptions\n});\nawait graphInstance.doLayout();\n```\n\nThis fragment shows how the UI keeps the two spacing controls mutually exclusive and connects both of them back to React state.\n\n```tsx\n\u003CSimpleUISelect\n  data={[\n    { value: '1', text: 'Set by Distance Coefficient' },\n    { value: '2', text: 'Set by Level Distance' }\n  ]}\n  currentValue={configType}\n  onChange={(newValue: string) => { setConfigType(parseInt(newValue)); }}\n/>\n\u003Cdiv style={{ display: configType === 1 ? 'block' : 'none', paddingTop: '10px' }}>\n  \u003Cdiv className=\"py-1\">Distance Coefficient: {distanceCoefficient}\u003C/div>\n\u003C/div>\n```\n\nThis fragment shows that the shared overlay is not only decorative; it directly drives relation-graph canvas behavior and the image-export flow.\n\n```tsx\nconst canvasDom = await graphInstance.prepareForImageGeneration();\nlet graphBackgroundColor = graphInstance.getOptions().backgroundColor;\nif (!graphBackgroundColor || graphBackgroundColor === 'transparent') {\n  graphBackgroundColor = '#ffffff';\n}\nconst imageBlob = await domToImageByModernScreenshot(canvasDom, {\n  backgroundColor: graphBackgroundColor\n});\nif (imageBlob) {\n  downloadBlob(imageBlob, 'my-image-name');\n}\nawait graphInstance.restoreAfterImageGeneration();\n```\n\n## What Makes This Example Distinct\n\nCompared with nearby layout playgrounds, this example stays tightly focused on one question: how spacing behaves inside the `center` layout when you switch between `distanceCoefficient` and `levelGaps`. That makes it more specific than `graph-angle-offset` or `switch-layout`, which compare multiple layout families or orientation settings instead of going deep on one layout's spacing rules.\n\nCompared with `layout-center`, this demo avoids batch restyling of nodes and lines and keeps the graph appearance nearly fixed. The centered teal hierarchy works as a visual probe, so the visible differences come from spacing alone.\n\nCompared with `tree-distance`, it applies the same runtime tuning pattern to the `center` layout rather than to a directional tree layout. The most distinctive combination here is a small read-only centered graph, two mutually exclusive spacing modes, raw and preset `levelGaps` strings, and a reusable floating utility window with canvas-mode switches and image export.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to internal tooling where teams need to calibrate hierarchy spacing before they settle on final defaults. Examples include org-chart spacing experiments, skill-tree tuning, product taxonomy viewers, dependency explorers, and capability maps with uneven depth.\n\nIt also works as a reusable pattern for small graph workbenches: keep one representative dataset fixed, expose only a few layout parameters, and rerun layout against the live graph instance. That approach is useful when the goal is parameter validation or design review rather than full graph editing.\n",false,500,1782615385065]