--- title: DragElementForce order: 8 --- ## Overview DragElementForce is a built-in behavior in G6 for implementing node dragging under `d3-force` and `d3-force-3d` layouts. During dragging, the layout is **recalculated in real-time**, allowing the graph layout to dynamically adjust to accommodate the new position of the nodes. Effect of DragElementForce ## Basic Usage Add this behavior in the graph configuration: **1. Quick Configuration (Static)** Declare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration: ```javascript const graph = new Graph({ // Other configurations... behaviors: ['drag-element-force'], }); ``` **2. Object Configuration (Recommended)** Configure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime: ```javascript const graph = new Graph({ // Other configurations... behaviors: [ { type: 'drag-element-force', key: 'drag-element-force-1', fixed: true, // Fix node position after dragging }, ], }); ``` ## Configuration Options | Option | Description | Type | Default | Required | | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- | | type | Behavior type name, set `type: 'drag-element-force'` to enable this behavior | string | `drag-element-force` | ✓ | | key | Unique identifier for the behavior, used for subsequent operations | string | - | | | fixed | Whether to keep the node position fixed after dragging ends, boolean values represent:
- true: After dragging ends, the node's position will remain fixed and not be affected by the layout algorithm
- false: After dragging ends, the node's position will continue to be affected by the layout algorithm | boolean | false | | | enable | Whether to enable the drag function, by default nodes and combos can be dragged | boolean \| ((event: IElementDragEvent) => boolean) | `['node', 'combo'].includes(event.targetType)` | | | state | Identifier for the selected state of nodes, when multi-selection is enabled, it will find the selected nodes based on this state | string | `selected` | | | hideEdge | Controls the display state of edges during dragging, optional values are:
- `none`: Do not hide any edges
- `out`: Hide edges with the current node as the source node
- `in`: Hide edges with the current node as the target node
- `both`: Hide all edges related to the current node
- `all`: Hide all edges in the graph
⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect. | `none` \| `all` \| `in` \| `out` \| `both` | `none` | | | cursor | Customize the mouse style during dragging, [example](#cursor) | { default?: Cursor; grab: Cursor; grabbing: Cursor } | - | | | trigger | Press this shortcut key in combination with mouse perform drag element **Key reference:** _MDN Key Values_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys
⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \| (`Control` \| `Shift`\| `Alt` \| `......`)[] | [`shift`] | | ### cursor `cursor` is used to customize the mouse pointer style during dragging: - `default`: Pointer style in default state - `grab`: Pointer style when hovering over a draggable element - `grabbing`: Pointer style when dragging Optional values are: `auto` | `default` | `none` | `context-menu` | `help` | `pointer` | `progress` | `wait` | `cell` | `crosshair` | `text` | `vertical-text` | `alias` | `copy` | `move` | `no-drop` | `not-allowed` | `grab` | `grabbing` | `all-scroll` | `col-resize` | `row-resize` | `n-resize` | `e-resize` | `s-resize` | `w-resize` | `ne-resize` | `nw-resize` | `se-resize` | `sw-resize` | `ew-resize` | `ns-resize` | `nesw-resize` | `nwse-resize` | `zoom-in` | `zoom-out` Example configuration: ```js cursor: { default: 'default', // Use normal pointer by default grab: 'grab', // Show grab pointer when draggable grabbing: 'grabbing' // Show grabbing pointer when dragging } ``` ## FAQ ### 1. What is the difference between DragElementForce and DragElement? - `DragElementForce` is specifically used for `d3-force` or `d3-force-3d` layouts, and recalculates the layout in real-time during dragging - `DragElement` is a general drag interaction and does not trigger layout recalculation ## Practical Example ### Mesh Effect ```js | ob { inject: true } import { Graph } from '@antv/g6'; function getData(size = 10) { const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` })); const edges = []; for (let y = 0; y < size; ++y) { for (let x = 0; x < size; ++x) { if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` }); if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` }); } } return { nodes, edges }; } const graph = new Graph({ data: getData(), layout: { type: 'd3-force', manyBody: { strength: -30, }, link: { strength: 1, distance: 20, iterations: 10, }, }, node: { style: { size: 10, fill: '#000', }, }, edge: { style: { stroke: '#000', }, }, behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'], }); graph.render(); window.addPanel((gui) => { gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable(); }); ``` ### Fix Dragged Nodes ```js | ob { inject: true } import { Graph } from '@antv/g6'; const data = { nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })), edges: [ { source: '0', target: '1' }, { source: '0', target: '2' }, { source: '0', target: '3' }, { source: '0', target: '4' }, { source: '0', target: '5' }, { source: '0', target: '7' }, { source: '0', target: '8' }, { source: '0', target: '9' }, { source: '2', target: '3' }, { source: '4', target: '5' }, { source: '4', target: '6' }, { source: '5', target: '6' }, ], }; const graph = new Graph({ container: 'container', data, node: { style: { labelText: (d) => d.label, labelPlacement: 'middle', labelFill: '#fff', }, }, layout: { type: 'd3-force', link: { distance: 100, strength: 2, }, collide: { radius: 40, }, }, behaviors: [ { type: 'drag-element-force', fixed: true, }, ], }); graph.render(); ``` ## Shadow Style ### shadow{[BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#%E7%BB%98%E5%9B%BE%E5%B1%9E%E6%80%A7)}
An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format. TextStyleProps includes the following properties: - fill - fontSize - fontWeight - ... icon{TextStyleProps} means you need to use the following property names: - iconFill - iconFontSize - iconFontWeight - ...