[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:canvas-selection-node-creation":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Canvas Selection for Picking and Shape Creation\n\n## What This Example Builds\nThis example builds a full-screen relation-graph workspace seeded with 14 disconnected lettered nodes. A draggable helper window stays above the canvas, explains how to start selection, shows the live selection rectangle metrics, and exposes toggles that change what the drag gesture does.\n\nThe core behavior is that one box-selection gesture has two possible outcomes. In normal mode it selects every node inside the dragged region. In creation mode it turns the same region into a new circle or rectangle node sized from the dragged box. That makes the example a compact reference for selection-driven tooling rather than a domain-specific chart.\n\n## How the Data Is Organized\nThe initial dataset is an inline `RGJsonData` object created inside `initializeGraph`. It contains a flat `nodes` array with ids `a` through `n`, and an empty `lines` array, so the starting point is intentionally simple and unconnected.\n\nThere is no external fetch and no preprocessing before `setJsonData(...)` beyond building that local object. After the data is loaded, the example centers and fits the graph in the viewport. During interaction, the selection rectangle becomes transient runtime input: it is either passed to `getNodesInSelectionView(...)` for multi-select, or converted to canvas coordinates and used to size a new node with `addNode(...)`.\n\nIn a production app, the same data shape could represent cards on a planning board, devices on a topology canvas, seats on a floor plan, or assets on an annotation workspace where region selection and region-based creation matter more than line relationships.\n\n## How relation-graph Is Used\nThe demo is wrapped in `RGProvider`, then `MyGraph` uses `RGHooks.useGraphInstance()` to load data, center the view, clear state, resolve nodes inside a selection, and insert new nodes. It also uses `RGHooks.useSelection()` so the current selection rectangle can drive both the floating status card and the temporary shape preview.\n\nThe graph options are small but deliberate: `showToolBar` enables the built-in toolbar, `checkedItemBackgroundColor` gives selected items a translucent green background, `defaultLineWidth` stays minimal, and `dragEventAction` is bound to React state so the canvas can switch between `selection` and `move` at runtime. The local code does not declare a custom layout; it loads the sample data and normalizes the viewport with `moveToCenter()` and `zoomToFit()`.\n\n`RelationGraph` receives the key event handlers, especially `onCanvasClick` and `onCanvasSelectionEnd`. `RGSlotOnNode` overrides node content with a padded text renderer. The floating `DraggableWindow` component adds the instructional panel and opens a shared settings panel that reads current options through `RGHooks.useGraphStore()`, updates wheel and drag behavior with `setOptions(...)`, and exports the graph image through `prepareForImageGeneration()` plus a DOM-to-image helper. The SCSS file only defines placeholder selectors, so most visible customization comes from JSX, Tailwind-style utility classes, and the SVG overlay in `MyCreatingShapeLayer`.\n\n## Key Interactions\n- Hold `Shift` to start canvas selection, or explicitly switch the canvas drag action into `selection` mode from the helper panel.\n- Drag a selection box in normal mode to find nodes inside the region and mark them selected.\n- Enable circle or rectangle creation, then drag the same selection box to insert a new node whose size comes from the dragged bounds.\n- Click empty canvas space to clear checked and selected graph state.\n- Open the floating settings panel to change wheel behavior, change drag behavior, or download the current graph as an image.\n\nNode-click and line-click handlers are present, but in this example they only log objects to the console and do not change the graph state.\n\n## Key Code Fragments\nThe graph instance, live selection state, and runtime drag mode are wired together at the top of `MyGraph`.\n\n```tsx\nconst graphInstance = RGHooks.useGraphInstance();\nconst selectionView = RGHooks.useSelection();\nconst [dragMode, setDragMode] = React.useState\u003C'move'|'selection'>('selection');\nconst [selectionForCreateNode, setSelectionForCreateNode] = React.useState\u003C''|'circle'|'rect'>('');\n\nconst graphOptions: RGOptions = {\n    debug: false,\n    showToolBar: true,\n    checkedItemBackgroundColor: 'rgba(0, 128, 0, 0.2)',\n    defaultLineWidth: 1,\n    dragEventAction: dragMode,\n    defaultJunctionPoint: RGJunctionPoint.border\n};\n```\n\nThe initial graph data is local, lightweight, and loaded directly into the relation-graph instance before the view is centered and fitted.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    nodes: [\n        { id: 'a', text: 'A' },\n        { id: 'b', text: 'B' },\n        // ...\n    ],\n    lines: []\n};\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\n`onCanvasSelectionEnd` turns the selection rectangle into a new node when a creation mode is armed.\n\n```tsx\nif (selectionForCreateNode === 'circle') {\n    const xyOnCanvas = graphInstance.getCanvasXyByViewXy(userSelectionView);\n    graphInstance.addNode({\n        id: graphInstance.generateNewNodeId(),\n        nodeShape: RGNodeShape.circle,\n        width: userSelectionView.width,\n        height: userSelectionView.height,\n        x: xyOnCanvas.x,\n        y: xyOnCanvas.y\n    });\n}\n```\n\nThe non-creation branch uses relation-graph's built-in selection query to resolve existing nodes and mark them selected.\n\n```tsx\ngraphInstance.clearChecked();\ngraphInstance.clearSelected();\nconst nodesInSelection = graphInstance.getNodesInSelectionView(userSelectionView);\nSimpleGlobalMessage.success(`Select [${nodesInSelection.length}] Nodes`);\nnodesInSelection.forEach(node => {\n   graphInstance.updateNode(node, { selected: true })\n});\n```\n\nThe temporary overlay normalizes negative drag directions so the preview still renders correctly when the user drags leftward or upward.\n\n```tsx\nconst rectX = width > 0 ? x : x + width;\nconst rectY = height > 0 ? y : y + height;\nconst absWidth = Math.abs(width);\nconst absHeight = Math.abs(height);\n\n{shape === 'rect' ? (\n    \u003Crect\n        x={rectX}\n        y={rectY}\n        width={absWidth}\n        height={absHeight}\n        strokeDasharray=\"4 2\"\n    />\n) : (\n    \u003Ccircle\n        cx={rectX + absWidth / 2}\n        cy={rectY + absHeight / 2}\n        r={Math.min(absWidth, absHeight) / 2}\n    />\n)}\n```\n\n## What Makes This Example Distinct\nCompared with [`selections`](./selections), this example does not treat marquee selection as the final outcome. The dragged region can still select existing nodes, but it can also become new graph content. That shifts the example from pure picking into hybrid selection-and-authoring.\n\nCompared with [`canvas-selection-pro`](./canvas-selection-pro), the emphasis here is explicit teaching rather than shortcut-first speed. The helper window keeps move-or-selection mode and circle-or-rectangle creation visible at all times, so the workflow is easier to study and adapt.\n\nThe comparison data also shows a distinct feature combination: manual canvas mode switching, click-to-clear workspace behavior, live selection instrumentation, a dashed creation preview, and selection-driven node insertion in one compact screen. Other nearby examples cover parts of that pattern, but this one is a particularly focused reference when you want relation-graph's native selection geometry to be the central interaction primitive.\n\n## Where Else This Pattern Applies\nThis pattern transfers well to lightweight whiteboard editors where a dragged region can either select existing objects or create a new bounded shape. It also fits planning boards, floor-plan tools, topology sketchers, and annotation canvases where the same gesture should support both region-based picking and region-based insertion.\n\nAnother extension path is to treat the selection rectangle as a generic input primitive. Instead of creating only circle and rectangle nodes, the same handoff could create grouped cards, bounded containers, placeholder devices, or domain-specific regions once the user chooses a creation mode.\n",false,500,1782615424361]