[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:tree-layout-orientation-switcher":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Tree Layout Orientation Switching with Live Relayout\n\n## What This Example Builds\n\nThis example builds a read-only hierarchy viewer for a company wiki directory. The same tree can be shown as a left-to-right tree or a top-down tree without loading a second dataset.\n\nUsers can switch the layout direction from a floating selector, inspect the graph through an embedded mini view, and open the shared canvas settings window for drag, wheel, and image-export utilities. The main point of the example is that it relayouts an already loaded graph and reapplies orientation-specific node sizing, connector settings, and text formatting before the next layout pass.\n\n## How the Data Is Organized\n\nThe data comes from an async local `getMockData()` function that returns one `RGJsonData` object with `rootId`, a flat `nodes` array, and a flat `lines` array. The content represents a documentation-style hierarchy: a root wiki directory, several top-level sections, and deeper policy, project, and support branches.\n\nThere is no preprocessing before `setJsonData(...)` runs. The only runtime transformation happens after the data is already mounted: when the orientation changes, the code selects a preset, rewrites each existing node's width and height, rewrites each existing line's shape, then calls `doLayout()`.\n\nIn a real application, the same structure could represent a knowledge base, policy manual, learning catalog, content taxonomy, or any other tree where the same hierarchy must remain readable in more than one orientation.\n\n## How relation-graph Is Used\n\nThe example is wrapped in `RGProvider`, and `MyGraph` uses `RGHooks.useGraphInstance()` as the main runtime API surface. Two `RGOptions` presets drive the graph. Both use `layoutName: 'tree'`, but the horizontal preset uses `from: 'left'`, large horizontal spacing, auto-sized rectangular nodes, left-right junctions, and white nodes with gray lines. The vertical preset uses `from: 'top'`, tall narrow rectangles, top-bottom junctions, and borderless gray nodes.\n\nThe graph is initialized by awaiting `getMockData()` and passing the result to `setJsonData(...)`. After that, a `useEffect` reacts to `layoutFrom` changes and runs the relayout sequence. The code calls `setOptions(...)`, iterates over `getNodes()` plus `updateNode(...)` to normalize live node dimensions, iterates over `getLines()` plus `updateLine(...)` to normalize line shape, waits with `sleep(100)`, then runs `doLayout()`, `moveToCenter()`, and `zoomToFit()`.\n\nThe example does not use custom node or line slots. Instead, it keeps the built-in rendering and customizes it through options plus SCSS. `RGSlotOnView` mounts `RGMiniView` as a viewport overlay, and the wrapper class switches to `.my-layout-top` so the top-down mode can apply `writing-mode: vertical-rl` to built-in node labels. The floating `DraggableWindow` is a shared helper component; inside it, `CanvasSettingsPanel` uses relation-graph hooks to change wheel and drag behavior and to export the canvas through `prepareForImageGeneration()` and `restoreAfterImageGeneration()`.\n\n## Key Interactions\n\nThe primary interaction is layout orientation switching. Clicking the `SimpleUISelect` control changes `layoutFrom`, which triggers a full relayout of the mounted graph rather than rebuilding the dataset from scratch.\n\nThe floating helper window can be dragged, minimized, and expanded into a settings panel. That panel changes wheel behavior, changes canvas drag behavior, and downloads a generated image of the graph.\n\nNode and line click handlers are present, but they only log the clicked objects. They do not drive layout, navigation, or editing.\n\n## Key Code Fragments\n\nThis fragment shows that the data model is a single static `RGJsonData` tree with one root and flat node and line arrays.\n\n```ts\nexport const getMockData = async() => {\n    return {\n        \"rootId\": \"1\",\n        \"nodes\": [\n            {\n                \"id\": \"1\",\n                \"text\": \"Company Wiki Directory\"\n            },\n```\n\nThis fragment shows the horizontal preset: built-in `tree` layout, left-to-right direction, large horizontal spacing, and auto-sized rectangular nodes.\n\n```tsx\nconst graphOptionsH: RGOptions = {\n    layout: {\n        layoutName: 'tree',\n        treeNodeGapH: 300,\n        treeNodeGapV: 10,\n        from: 'left'\n    },\n    defaultNodeShape: RGNodeShape.rect,\n    defaultNodeWidth: 0,\n    defaultNodeHeight: 0,\n```\n\nThis fragment proves that orientation changes normalize already loaded node and line state before the next layout pass.\n\n```tsx\nconst targetOptions = layoutFrom === 'left' ? graphOptionsH : graphOptionsV;\ngraphInstance.setOptions(targetOptions);\ngraphInstance.getNodes().forEach((node) => {\n    graphInstance.updateNode(node, {\n        width: targetOptions.defaultNodeWidth,\n        height: targetOptions.defaultNodeHeight\n    });\n});\ngraphInstance.getLines().forEach((line) => {\n    graphInstance.updateLine(line, {\n        lineShape: targetOptions.defaultLineShape\n    });\n});\n```\n\nThis fragment shows that the relayout flow waits for the DOM to settle, then recomputes layout and refits the viewport.\n\n```tsx\nawait graphInstance.sleep(100);\nawait graphInstance.doLayout();\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis fragment shows the runtime control that switches between horizontal and vertical presets.\n\n```tsx\n\u003CSimpleUISelect\n    data={[\n        { value: 'left', text: 'Horizontal Tree' },\n        { value: 'top', text: 'Vertical Tree' }\n    ]}\n    currentValue={layoutFrom}\n    onChange={(newValue: string) => { setLayoutFrom(newValue); }}\n/>\n```\n\nThis fragment shows the top-down style override that changes built-in node labels to vertical writing.\n\n```scss\n.my-graph.my-layout-top {\n    .relation-graph {\n        .rg-node-peel {\n            .rg-node {\n                .rg-node-text {\n                    padding-top: 10px;\n                    justify-content: flex-start;\n                    writing-mode: vertical-rl;\n                }\n            }\n        }\n    }\n}\n```\n\n## What Makes This Example Distinct\n\nThe comparison data shows that this example stands out less for having a layout switcher by itself and more for how it handles the switch. Its main distinguishing pattern is switching one already loaded hierarchy between ordinary `tree` presets while explicitly rewriting live node widths, heights, and line shapes before `doLayout()`.\n\nThat makes it a cleaner reference than `io-tree-layout` when the goal is ordinary tree orientation switching rather than level-aware IO routing. Compared with `bothway-tree2`, it focuses on one-direction hierarchy readability and relayout normalization on mounted graph objects instead of bidirectional branches and line-label controls. Compared with `industry-chain` and `layout-folder2`, it keeps nodes visually simple so the main lesson stays on orientation-specific sizing, junction defaults, curved connectors, and label flow.\n\nThe rarity and comparison records also highlight an unusual visual pairing: horizontal mode uses auto-sized white rectangles, while top-down mode uses 30-by-260 narrow rectangles with vertical text. That combination makes this example a strong starting point when the same hierarchy must remain readable in two substantially different reading directions.\n\n## Where Else This Pattern Applies\n\nThis pattern applies to documentation trees, policy manuals, course outlines, product taxonomies, and support knowledge bases where the same hierarchy may need both a wide exploratory view and a narrow top-down presentation.\n\nIt also transfers to cases where a team must restyle a mounted graph without rebuilding its data model. The same relayout sequence can be adapted for print layouts, language-specific label flow, kiosk displays, or view-mode switches that need different node dimensions and connector defaults on the same underlying tree.\n",false,500,1782615382777]